diff --git a/conf/app.src b/conf/app.src index 7b9885e..32826a6 100644 --- a/conf/app.src +++ b/conf/app.src @@ -1,5 +1,5 @@ -SOURCE_URL=https://code.ffdn.org/FFDN/coin/archive/571df323feac6cb8fb338a8341bbd8c329f0d238.tar.gz -SOURCE_FILENAME=coin-2018-08-17-2.tar.gz +SOURCE_URL=https://code.ffdn.org/ffdn/coin/-/archive/d13c762172e08c8b7caa482719132d2813cf6042/coin-d13c762172e08c8b7caa482719132d2813cf6042.tar.gz +SOURCE_FILENAME=coin-d13c762172e08c8b7caa482719132d2813cf6042.tar.gz SOURCE_FORMAT=tar.gz -SOURCE_SUM=09026019017592ea178e19a54443dbe928d191c13d7bb030c50e9e267988bf98 +SOURCE_SUM=4a1da429dd65f407b37f95adb7e379035af222493e41c2c9f65835d492bb7c4a SOURCE_SUM_PRG=sha256sum diff --git a/conf/gunicorn_config.py b/conf/gunicorn_config.py index 0cab25c..7e6c034 100644 --- a/conf/gunicorn_config.py +++ b/conf/gunicorn_config.py @@ -1,11 +1,11 @@ -command = '/opt/YNH_APP_INSTANCE_NAME/venv/bin/gunicorn' -pythonpath = '/opt/YNH_APP_INSTANCE_NAME' +command = '/opt/__YNH_APP_INSTANCE_NAME__/venv/bin/gunicorn' +pythonpath = '/opt/__YNH_APP_INSTANCE_NAME__' workers = 4 -user = 'YNH_APP_INSTANCE_NAME' -bind = 'unix:/opt/YNH_APP_INSTANCE_NAME/sock' -pid = '/run/gunicorn/YNH_APP_INSTANCE_NAME-pid' -errorlog = '/var/log/YNH_APP_INSTANCE_NAME/error.log' -accesslog = '/var/log/YNH_APP_INSTANCE_NAME/access.log' +user = '__YNH_APP_INSTANCE_NAME__' +bind = 'unix:/opt/__YNH_APP_INSTANCE_NAME__/sock' +pid = '/run/gunicorn/__YNH_APP_INSTANCE_NAME__-pid' +errorlog = '/var/log/__YNH_APP_INSTANCE_NAME__/error.log' +accesslog = '/var/log/__YNH_APP_INSTANCE_NAME__/access.log' access_log_format = '%({X-Real-IP}i)s %({X-Forwarded-For}i)s %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"' loglevel = 'warning' capture_output = True diff --git a/conf/local.py.j2 b/conf/local.py.j2 new file mode 100644 index 0000000..b260fee --- /dev/null +++ b/conf/local.py.j2 @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +import os +from settings_base import * + +DEBUG = TEMPLATE_DEBUG = False + +ALLOWED_HOSTS = ['{{ domain }}'] + +URL_PREFIX = '{{ prefix }}' +STATIC_ROOT = '{{ final_path }}/static' +NOTIFICATION_EMAILS = ['{{ email }}'] +DEFAULT_FROM_EMAIL = 'notifier@{{ domain }}' +SITE_URL = "https://{{ domain }}{{ path_url }}" +SECRET_KEY = '{{ secret }}' +ISP = { + 'NAME': '{{ isp_name }}', + 'SITE': '{{ isp_site }}', + 'EMAIL': '{{ email }}', +} +SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') + +PROJECT_DIR = os.path.abspath(os.path.dirname(__file__)) + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + 'NAME': '{{ db_name }}', + 'USER': '{{ db_user }}', + 'PASSWORD': '{{ db_pwd }}', + 'HOST': '127.0.0.1', + 'PORT': '5432', + }, +} + +FEEDS = (('ffdn', 'http://www.ffdn.org/fr/rss.xml', 3),) + + + + + + + + + + + + + + + + + + + + + +# Tous acces +# parametrer SSO en protect_uris +# OU +# Pas d'acces +# hook +# parametrer SSO en protect_uris +import ldap +from django_auth_ldap.config import LDAPSearch, PosixGroupType +AUTHENTICATION_BACKENDS = ( + 'django_auth_ldap.backend.LDAPBackend', + 'django.contrib.auth.backends.ModelBackend', +) +AUTH_LDAP_SERVER_URI = "ldap://localhost:389" +AUTH_LDAP_USER_SEARCH = LDAPSearch("uid={{ admin }},ou=users,dc=yunohost,dc=org", ldap.SCOPE_SUBTREE, "(uid=%(user)s)") +AUTH_LDAP_USER_ATTR_MAP = { + "username": "uid", + "first_name": "givenName", + "last_name": "sn", + "email": "mail", +} +AUTH_LDAP_USER_FLAGS_BY_GROUP = { + "is_active": "cn=sftpusers,ou=groups,dc=yunohost,dc=org", + "is_staff": "cn=sftpusers,ou=groups,dc=yunohost,dc=org", + "is_superuser": "cn=sftpusers,ou=groups,dc=yunohost,dc=org" +} +AUTH_LDAP_GROUP_SEARCH = LDAPSearch("ou=groups,dc=yunohost,dc=org", ldap.SCOPE_SUBTREE, "(objectClass=posixGroup)") +AUTH_LDAP_GROUP_TYPE = PosixGroupType() +AUTH_LDAP_ALWAYS_UPDATE_USER = True +AUTH_LDAP_AUTHORIZE_ALL_USERS = True +AUTH_LDAP_FIND_GROUP_PERMS = True +#AUTH_LDAP_CACHE_GROUPS = True +#AUTH_LDAP_GROUP_CACHE_TIMEOUT = 300 +#import logging +#logger = logging.getLogger('django_auth_ldap') +#logger.addHandler(logging.StreamHandler()) +#logger.setLevel(logging.DEBUG) diff --git a/conf/nginx.conf b/conf/nginx.conf index 27fcfcc..36fa9f3 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,30 +1,31 @@ -location PATHTOCHANGE { - if ($scheme = http) { - rewrite ^ https://$server_name$request_uri? permanent; - } - try_files $uri @YNH_APP_INSTANCE_NAME; -} -location /protected/ { - internal; - alias /opt/YNH_APP_INSTANCE_NAME/YNH_APP_INSTANCE_NAME/smedia/; -} - -location PATHTOCHANGEmedia { - alias /opt/YNH_APP_INSTANCE_NAME/media; -} - -location PATHTOCHANGEstatic { - alias /opt/YNH_APP_INSTANCE_NAME/static; -} - -location PATHTOCHANGEassets { - alias /opt/YNH_APP_INSTANCE_NAME/static; -} - -location @YNH_APP_INSTANCE_NAME { - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_pass http://unix:/opt/YNH_APP_INSTANCE_NAME/sock; -} +#sub_path_only rewrite ^__PATH__$ __PATH__/ permanent; +location __PATH__/ { + if ($scheme = http) { + rewrite ^ https://$server_name$request_uri? permanent; + } + try_files $uri @__NAME__; +} +location __PATH__/protected/ { + internal; + alias /opt/__NAME__/__NAME__/smedia/; +} + +location __PATH__/media { + alias /opt/__NAME__/media; +} + +location __PATH__/static { + alias /opt/__NAME__/static; +} + +location __PATH__/assets { + alias /opt/__NAME__/static; +} + +location @__NAME__ { + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_pass http://unix:/opt/__NAME__/sock; +} diff --git a/conf/systemd.service b/conf/systemd.service new file mode 100644 index 0000000..b2e15da --- /dev/null +++ b/conf/systemd.service @@ -0,0 +1,16 @@ +[Unit] +Description=__APP__ gunicorn daemon +After=network.target + +[Service] +PIDFile=/run/gunicorn/__APP__-pid +User=__APP__ +Group=__APP__ +WorkingDirectory=__FINALPATH__/ +ExecStart=__FINALPATH__/venv/bin/gunicorn -c __FINALPATH__/gunicorn_config.py __APP__.wsgi +ExecReload=/bin/kill -s HUP $MAINPID +ExecStop=/bin/kill -s TERM $MAINPID +PrivateTmp=true + +[Install] +WantedBy=multi-user.target diff --git a/manifest.json b/manifest.json index 8059b7f..5005b1c 100644 --- a/manifest.json +++ b/manifest.json @@ -14,10 +14,10 @@ }, "url": "https://code.ffdn.org/FFDN/coin/", "requirements": { - "yunohost": ">> 3.0" + "yunohost": ">= 3.6" }, - "version": "20180817~ynh4", - "multi_instance": false, + "version": "20190823~ynh1", + "multi_instance": true, "services": [ "nginx" ], diff --git a/scripts/_common.sh b/scripts/_common.sh new file mode 100644 index 0000000..0154701 --- /dev/null +++ b/scripts/_common.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +#================================================= +# COMMON VARIABLES +#================================================= + +# dependencies used by the app +pkg_dependencies="python-virtualenv gunicorn python-dev python-pip libldap2-dev libpq-dev libsasl2-dev libjpeg-dev libxml2-dev libxslt1-dev libffi-dev python-cairo libpango1.0-0 postgresql postgresql-contrib" + +#================================================= +# PERSONAL HELPERS +#================================================= + +#================================================= +# EXPERIMENTAL HELPERS +#================================================= + +#================================================= +# FUTURE OFFICIAL HELPERS +#================================================= diff --git a/scripts/backup b/scripts/backup index 1a6d84d..cf9221a 100644 --- a/scripts/backup +++ b/scripts/backup @@ -1,23 +1,85 @@ #!/bin/bash -# Exit on command errors and treat unset variables as an error -set -eu +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +#Keep this path for calling _common.sh inside the execution's context of backup and restore scripts +source ../settings/scripts/_common.sh +source /usr/share/yunohost/helpers + +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= + +ynh_clean_setup () { + ### Remove this function if there's nothing to clean before calling the remove script. + true +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." --time --weight=1 -# See comments in install script app=$YNH_APP_INSTANCE_NAME -# Source YunoHost helpers -. /usr/share/yunohost/helpers +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +domain=$(ynh_app_setting_get --app=$app --key=domain) +db_name=$(ynh_app_setting_get --app=$app --key=db_name) -# Backup sources & data -ynh_backup "/opt/$app" "sources" +#================================================= +# STANDARD BACKUP STEPS +#================================================= +# STOP SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Stopping a systemd service..." --time --weight=1 -# Copy NGINX configuration -domain=$(ynh_app_setting_get "$app" domain) -ynh_backup "/etc/nginx/conf.d/${domain}.d/${app}.conf" "nginx.conf" +ynh_systemd_action --service_name=$app --action="stop" --log_path="/var/log/$app/$app.log" -# Copy Gunicorn pool configuration -ynh_backup "/etc/systemd/system/$app.service" "gunicorn.service" +#================================================= +# BACKUP THE APP MAIN DIR +#================================================= +ynh_script_progression --message="Backing up the main app directory..." --time --weight=1 -# Backup database -ynh_psql_dump_db "$app" > ${YNH_CWD}/dump.sql +ynh_backup --src_path="$final_path" + +#================================================= +# BACKUP THE NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Backing up nginx web server configuration..." --time --weight=1 + +ynh_backup --src_path="/etc/nginx/conf.d/$domain.d/$app.conf" + +#================================================= +# BACKUP THE PSQL DATABASE +#================================================= +ynh_script_progression --message="Backing up the PSQL database..." --time --weight=1 + +ynh_psql_dump_db --database="$db_name" > db.sql + +#================================================= +# SPECIFIC BACKUP +#================================================= +# BACKUP SYSTEMD +#================================================= +ynh_script_progression --message="Backing up systemd configuration..." --time --weight=1 + +ynh_backup --src_path="/etc/systemd/system/$app.service" + +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." --time --weight=1 + +ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Backup script completed for $app. (YunoHost will then actually copy those files to the archive)." --time --last diff --git a/scripts/change_url b/scripts/change_url new file mode 100644 index 0000000..17a1e41 --- /dev/null +++ b/scripts/change_url @@ -0,0 +1,117 @@ +#!/bin/bash + +#================================================= +# GENERIC STARTING +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source _common.sh +source /usr/share/yunohost/helpers + +#================================================= +# RETRIEVE ARGUMENTS +#================================================= + +old_domain=$YNH_APP_OLD_DOMAIN +old_path=$YNH_APP_OLD_PATH + +new_domain=$YNH_APP_NEW_DOMAIN +new_path=$YNH_APP_NEW_PATH + +app=$YNH_APP_INSTANCE_NAME + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." --time --weight=1 + +# Needed for helper "ynh_add_nginx_config" +final_path=$(ynh_app_setting_get --app=$app --key=final_path) + +# Add settings here as needed by your application +#db_name=$(ynh_app_setting_get --app=$app --key=db_name) +#db_user=$db_name +#db_pwd=$(ynh_app_setting_get --app=$app --key=db_pwd) + +#================================================= +# CHECK WHICH PARTS SHOULD BE CHANGED +#================================================= + +change_domain=0 +if [ "$old_domain" != "$new_domain" ] +then + change_domain=1 +fi + +change_path=0 +if [ "$old_path" != "$new_path" ] +then + change_path=1 +fi + +#================================================= +# STANDARD MODIFICATIONS +#================================================= +# STOP SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Stopping a systemd service..." --time --weight=1 + +ynh_systemd_action --service_name=$app --action="stop" --log_path="/var/log/$app/$app.log" + +#================================================= +# MODIFY URL IN NGINX CONF +#================================================= +ynh_script_progression --message="Updating nginx web server configuration..." --time --weight=1 + +nginx_conf_path=/etc/nginx/conf.d/$old_domain.d/$app.conf + +# Change the path in the nginx config file +if [ $change_path -eq 1 ] +then + # Make a backup of the original nginx config file if modified + ynh_backup_if_checksum_is_different --file="$nginx_conf_path" + # Set global variables for nginx helper + domain="$old_domain" + path_url="$new_path" + # Create a dedicated nginx config + ynh_add_nginx_config +fi + +# Change the domain for nginx +if [ $change_domain -eq 1 ] +then + # Delete file checksum for the old conf file location + ynh_delete_file_checksum --file="$nginx_conf_path" + mv $nginx_conf_path /etc/nginx/conf.d/$new_domain.d/$app.conf + # Store file checksum for the new config file location + ynh_store_file_checksum --file="/etc/nginx/conf.d/$new_domain.d/$app.conf" +fi + +#================================================= +# SPECIFIC MODIFICATIONS +#================================================= +# ... +#================================================= + +#================================================= +# GENERIC FINALISATION +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." --time --weight=1 + +ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" + +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading nginx web server..." --time --weight=1 + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Change of URL completed for $app" --time --last diff --git a/scripts/install b/scripts/install index 5adc56a..371aac8 100644 --- a/scripts/install +++ b/scripts/install @@ -1,145 +1,229 @@ #!/bin/bash -# Exit on command errors and treat unset variables as an error -set -eu +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= -# Source YunoHost helpers +source _common.sh source /usr/share/yunohost/helpers -source future.sh -source common.sh -app=$YNH_APP_INSTANCE_NAME +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= -# Retrieve arguments -domain=$YNH_APP_ARG_DOMAIN -#readonly path=$YNH_APP_ARG_PATH -path=/ - -readonly admin=$YNH_APP_ARG_ADMIN -readonly email=$YNH_APP_ARG_EMAIL - - -readonly isp_name=$YNH_APP_ARG_ISP_NAME -readonly isp_site=$YNH_APP_ARG_ISP_SITE -readonly secret=$(ynh_string_random 24) # A bug don't allow to do random string bigger than 24 - - -# Check if admin exists -ynh_user_exists $admin \ - || ynh_die "Wrong admin" - -function configure_app() -{ - # Check domain/path availability - ynh_webpath_register "$app" "$domain" "$path" - - ynh_app_setting_set "$app" admin "$admin" - ynh_app_setting_set "$app" email "$email" - ynh_app_setting_set "$app" isp_name "$isp_name" - ynh_app_setting_set "$app" isp_site "$isp_site" - ynh_app_setting_set "$app" secret "$secret" +ynh_clean_setup () { + ### Remove this function if there's nothing to clean before calling the remove script. + read } +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors -function install_from_sources() -{ - $final_path/venv/bin/pip install "pip>=1.5.6" +#================================================= +# RETRIEVE ARGUMENTS FROM THE MANIFEST +#================================================= +export domain=$YNH_APP_ARG_DOMAIN +export path_url=/ +export admin=$YNH_APP_ARG_ADMIN +export email=$YNH_APP_ARG_EMAIL +export isp_name=$YNH_APP_ARG_ISP_NAME +export isp_site=$YNH_APP_ARG_ISP_SITE +is_public=1 +export secret=$(ynh_string_random 24) + +export app=$YNH_APP_INSTANCE_NAME + +#================================================= +# CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS +#================================================= +ynh_script_progression --message="Validating installation parameters..." --time --weight=1 + +export final_path=/opt/$app +test ! -e "$final_path" || ynh_die --message="This path already contains a folder" + +# Register (book) web path +ynh_webpath_register --app=$app --domain=$domain --path_url=$path_url + +#================================================= +# STORE SETTINGS FROM MANIFEST +#================================================= +ynh_script_progression --message="Storing installation settings..." --time --weight=1 + +ynh_app_setting_set --app=$app --key=domain --value=$domain +ynh_app_setting_set --app=$app --key=path --value=$path_url +ynh_app_setting_set --app=$app --key=is_public --value=$is_public +ynh_app_setting_set --app=$app --key=admin --value=$admin +ynh_app_setting_set --app=$app --key=email --value=$email +ynh_app_setting_set --app=$app --key=isp_name --value=$isp_name +ynh_app_setting_set --app=$app --key=isp_site --value=$isp_site + +#================================================= +# STANDARD MODIFICATIONS +#================================================= +# INSTALL DEPENDENCIES +#================================================= +ynh_script_progression --message="Installing dependencies..." --time --weight=1 + +ynh_install_app_dependencies $pkg_dependencies + +#================================================= +# CREATE DATABASE +#================================================= +ynh_script_progression --message="Creating a MySQL database..." --time --weight=1 + +ynh_psql_test_if_first_run + +export db_name=$(ynh_sanitize_dbid --db_name=$app) +export db_user=$db_name +ynh_app_setting_set --app=$app --key=db_name --value=$db_name +ynh_psql_setup_db --db_user=$db_user --db_name=$db_name +export db_pwd + +#================================================= +# DOWNLOAD, CHECK AND UNPACK SOURCE +#================================================= +ynh_script_progression --message="Setting up source files..." --time --weight=1 + +ynh_app_setting_set --app=$app --key=final_path --value=$final_path +# Download, check integrity, uncompress and patch the source from app.src +ynh_setup_source --dest_dir="$final_path" + +#================================================= +# NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Configuring nginx web server..." --time --weight=1 + +# Create a dedicated nginx config +ynh_add_nginx_config + +#================================================= +# CREATE DEDICATED USER +#================================================= +ynh_script_progression --message="Configuring system user..." --time --weight=1 + +# Create a system user +ynh_system_user_create --username=$app + +#================================================= +# SPECIFIC SETUP +#================================================= +# PYTHON DEPENDENCIES +#================================================= +virtualenv "$final_path/venv" +( + set +o nounset + source "${final_path}/venv/bin/activate" + set -o nounset + $final_path/venv/bin/pip install --upgrade pip $final_path/venv/bin/pip install gunicorn echo "django-auth-ldap<1.4" >> $final_path/requirements.txt $final_path/venv/bin/pip install -r $final_path/requirements.txt - #$final_path/venv/bin/pip install mysqlclient +) - prefix="${path#"/"}/" - prefix=${prefix%"/"} - # Configuration Django - sed -i "s@YNH_APP_ARG_ADMIN@$admin@g" ../conf/local.py - sed -i "s@YNH_APP_ARG_DOMAIN@$domain@g" ../conf/local.py - sed -i "s@YNH_APP_ARG_PATH@$path@g" ../conf/local.py - sed -i "s@YNH_APP_PREFIX@$prefix@g" ../conf/local.py - sed -i "s#YNH_APP_ARG_EMAIL#$email#g" ../conf/local.py - sed -i "s#YNH_APP_SECRET_KEY#$secret#g" ../conf/local.py - sed -i "s#YNH_APP_ARG_ISP_NAME#$isp_name#g" ../conf/local.py - sed -i "s#YNH_APP_ARG_ISP_SITE#$isp_site#g" ../conf/local.py - sed -i "s#YNH_APP_STATIC_ROOT#$final_path/static#g" ../conf/local.py - sed -i "s#YNH_DB_NAME#$db_name#g" ../conf/local.py - sed -i "s#YNH_DB_USER#$db_user#g" ../conf/local.py - sed -i "s#YNH_DB_PASSWORD#$db_pwd#g" ../conf/local.py - sudo cp ../conf/local.py $final_path/$app/settings_local.py +#================================================= +# CONFIGURATION DJANGO +#================================================= - # Set production - sudo ln -s $final_path/$app/static $final_path/static +export prefix="${path_url#"/"}/" +prefix=${prefix%"/"} +ynh_render_template ../conf/local.py.j2 "$final_path/coin/settings_local.py" +ynh_store_file_checksum --file="$final_path/coin/settings_local.py" - # Set permissions - sudo useradd $app -d $final_path || echo "User already exists" - sudo chown -R $app:www-data $final_path +#================================================= +# SERVE STATIC FILES IN PRODUCTION MODE +#================================================= +ln -s $final_path/$app/static $final_path/static + +#================================================= +# SETUP DATABASE +#================================================= +# Set permissions +chown -R $app:www-data $final_path + +pushd $final_path +$final_path/venv/bin/python manage.py migrate --noinput +$final_path/venv/bin/python manage.py collectstatic --noinput +popd + +# Set permissions to directory +chown $app:www-data -R $final_path + +#================================================ +# CONFIGURE LOG DIR +#================================================ +mkdir -p /var/log/$app +chown -R $app /var/log/$app +chgrp -R www-data /var/log/$app + +#================================================ +# SETUP GUNICORN +#================================================ +ynh_replace_string --match_string="__YNH_APP_INSTANCE_NAME__" --replace_string="$app" --target_file="../conf/gunicorn_config.py" +cp ../conf/gunicorn_config.py $final_path/ +ynh_store_file_checksum --file="$final_path/gunicorn_config.py" + +chown $app:www-data $final_path/gunicorn_config.py + +#================================================= +# SETUP SYSTEMD +#================================================= +ynh_script_progression --message="Configuring a systemd service..." --time --weight=1 + +# Create a dedicated systemd config +ynh_add_systemd_config - pushd $final_path - $final_path/venv/bin/python manage.py migrate --noinput - $final_path/venv/bin/python manage.py collectstatic --noinput - popd - # Set permissions to directory - sudo chown $app:www-data -R $final_path -} +#================================================= +# GENERIC FINALIZATION +#================================================= +# SECURE FILES AND DIRECTORIES +#================================================= -function configure_log() -{ - # Log folder - sudo mkdir -p /var/log/$app - sudo chown -R $app /var/log/$app - sudo chgrp -R www-data /var/log/$app -} +### For security reason, any app should set the permissions to root: before anything else. +### Then, if write authorization is needed, any access should be given only to directories +### that really need such authorization. -function configure_gunicorn() -{ - # Service gunicorn - sudo sed -i "s@YNH_APP_INSTANCE_NAME@$app@g" ../conf/gunicorn_config.py - sudo sed -i "s@YNH_APP_INSTANCE_NAME@$app@g" ../conf/gunicorn.service - sudo cp ../conf/gunicorn.service /etc/systemd/system/$app.service - sudo systemctl daemon-reload - sudo cp ../conf/gunicorn_config.py /opt/$app/ - chown $app:www-data /opt/$app/gunicorn_config.py -} - -function configure_nginx_and_ssowat() -{ - # Reload Nginx and regenerate SSOwat conf - sudo yunohost app addaccess $app -u $admin - - # Modify Nginx configuration file and copy it to Nginx conf directory - sed -i "s@PATHTOCHANGE@$path@g" ../conf/nginx.conf - sed -i "s@ALIASTOCHANGE@$final_path/@g" ../conf/nginx.conf - sed -i "s@YNH_APP_INSTANCE_NAME@$app@g" ../conf/nginx.conf - sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/$app.conf - - ## Reload Nginx and regenerate SSOwat conf - sudo service nginx reload - sudo systemctl start $app - sudo systemctl enable $app - sudo yunohost service add $app -l /var/log/gunicorn/$app.log - - ynh_app_setting_set "$app" skipped_uris "/" - sudo yunohost app ssowatconf -} - -configure_app -install_dependencies -init_db +# Set permissions to app files +chown -R $app:www-data $final_path - # Copy files to the right place - final_path=/opt/$app - ynh_setup_source $final_path - - # Install venv - pip install virtualenv - virtualenv $final_path/venv - set +o nounset - source $final_path/venv/bin/activate - set -o nounset +#================================================= +# ADVERTISE SERVICE IN ADMIN PANEL +#================================================= +yunohost service add $app --description "$app daemon" --log "/var/log/$app/$app.log" -install_from_sources -configure_log -configure_gunicorn -configure_nginx_and_ssowat +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." --time --weight=1 + +# Start a systemd service +ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" + +#================================================= +# SETUP SSOWAT +#================================================= +ynh_script_progression --message="Configuring SSOwat..." --time --weight=1 + +# Make app public if necessary +if [ $is_public -eq 1 ] +then + # unprotected_uris allows SSO credentials to be passed anyway. + ynh_app_setting_set --app=$app --key=unprotected_uris --value="/" +fi + +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading nginx web server..." --time --weight=1 + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Installation of $app completed" --time --last diff --git a/scripts/remove b/scripts/remove index b69c04b..2e99728 100644 --- a/scripts/remove +++ b/scripts/remove @@ -1,41 +1,98 @@ #!/bin/bash -set -u -# Source YunoHost helpers +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + source /usr/share/yunohost/helpers -source future.sh -source common.sh -# Retrieve app settings -APP=$YNH_APP_INSTANCE_NAME -app=$APP -DOMAIN=$(ynh_app_setting_get "$APP" domain) +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." --time --weight=1 -# FIXME FIXME FIXME -# Add tests that stuff actually exists before removing them +app=$YNH_APP_INSTANCE_NAME -# Remove mysql table -ynh_psql_remove_db $app $app +domain=$(ynh_app_setting_get --app=$app --key=domain) +port=$(ynh_app_setting_get --app=$app --key=port) +db_name=$(ynh_app_setting_get --app=$app --key=db_name) +db_user=$db_name +final_path=$(ynh_app_setting_get --app=$app --key=final_path) -# Remove dependencies +#================================================= +# STANDARD REMOVE +#================================================= +# REMOVE SERVICE FROM ADMIN PANEL +#================================================= + +# Remove a service from the admin panel, added by `yunohost service add` +if ynh_exec_warn_less yunohost service status $app >/dev/null +then + ynh_script_progression --message="Removing $app service..." --time --weight=1 + yunohost service remove $app +fi + +#================================================= +# STOP AND REMOVE SERVICE +#================================================= +ynh_script_progression --message="Stopping and removing the systemd service..." --time --weight=1 + +# Remove the dedicated systemd config +ynh_remove_systemd_config + +#================================================= +# REMOVE THE DATABASE +#================================================= +ynh_script_progression --message="Removing the database..." --time --weight=1 + +# Remove a database if it exists, along with the associated user +ynh_psql_remove_db --db_user=$db_user --db_name=$db_name + +#================================================= +# REMOVE DEPENDENCIES +#================================================= +ynh_script_progression --message="Removing dependencies..." --time --weight=1 + +# Remove metapackage and its dependencies ynh_remove_app_dependencies -# Remove nginx configuration file -sudo rm -f /etc/nginx/conf.d/$DOMAIN.d/$APP.conf +#================================================= +# REMOVE APP MAIN DIR +#================================================= +ynh_script_progression --message="Removing app main directory..." --time --weight=1 -# Remove services +# Remove the app directory securely +ynh_secure_remove --file="$final_path" -sudo service $APP stop -sudo killall $APP -sudo yunohost service remove $APP -sudo rm -f /etc/systemd/system/$APP.service -sudo systemctl daemon-reload +#================================================= +# REMOVE NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Removing nginx web server configuration..." --time --weight=1 -# Remove sources -ynh_secure_remove /opt/$APP +# Remove the dedicated nginx config +ynh_remove_nginx_config -# Delete system user -ynh_system_user_delete $APP +#================================================= +# SPECIFIC REMOVE +#================================================= -# Reload nginx service -sudo service nginx reload +# Remove the log files +ynh_secure_remove --file="/var/log/$app/" + +#================================================= +# GENERIC FINALIZATION +#================================================= +# REMOVE DEDICATED USER +#================================================= +ynh_script_progression --message="Removing the dedicated system user..." --time --weight=1 + +# Delete a system user +ynh_system_user_delete --username=$app + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Removal of $app completed" --time --last diff --git a/scripts/restore b/scripts/restore index 902cb6b..552f30e 100644 --- a/scripts/restore +++ b/scripts/restore @@ -1,86 +1,146 @@ #!/bin/bash -# Exit on command errors and treat unset variables as an error -set -eu +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= -# See comments in install script -app=$YNH_APP_INSTANCE_NAME +#Keep this path for calling _common.sh inside the execution's context of backup and restore scripts +source ../settings/scripts/_common.sh +source /usr/share/yunohost/helpers -# Source YunoHost helpers -. /usr/share/yunohost/helpers -source ../settings/scripts/common.sh +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= -# Retrieve old app settings -domain=$(ynh_app_setting_get "$app" domain) -path=$(ynh_app_setting_get "$app" path) -admin=$(ynh_app_setting_get "$app" admin) -email=$(ynh_app_setting_get "$app" email) -isp_name=$(ynh_app_setting_get "$app" isp_name) -isp_site=$(ynh_app_setting_get "$app" isp_site) -secret=$(ynh_app_setting_get "$app" secret) -db_pwd=$(ynh_app_setting_get "$app" psqlpassword) +ynh_clean_setup () { + #### Remove this function if there's nothing to clean before calling the remove script. + true +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors -# Check domain/path availability -sudo yunohost app checkurl $domain$path -a $app \ - || ynh_die "Path not available: ${domain}${path}" +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading settings..." --time --weight=1 +export app=$YNH_APP_INSTANCE_NAME -final_path=/opt/$app -if [ -d $final_path ]; then - ynh_die "There is already a directory: $final_path " -fi +export domain=$(ynh_app_setting_get --app=$app --key=domain) +export path_url=$(ynh_app_setting_get --app=$app --key=path) +export admin=$(ynh_app_setting_get --app=$app --key=admin) +export email=$(ynh_app_setting_get --app=$app --key=email) +export isp_name=$(ynh_app_setting_get --app=$app --key=isp_name) +export isp_site=$(ynh_app_setting_get --app=$app --key=isp_site) +export secret=$(ynh_app_setting_get --app=$app --key=secret) +export is_public=$(ynh_app_setting_get --app=$app --key=is_public) +export final_path=$(ynh_app_setting_get --app=$app --key=final_path) +export db_name=$(ynh_app_setting_get --app=$app --key=db_name) +export db_user=$db_name -conf=/etc/nginx/conf.d/$domain.d/$app.conf -if [ -f $conf ]; then - ynh_die "There is already a nginx conf file at this path: $conf " -fi +#================================================= +# CHECK IF THE APP CAN BE RESTORED +#================================================= +ynh_script_progression --message="Validating restoration parameters..." --time --weight=1 -gunicorn_path=/etc/systemd/system/$app.service -if [ -f $gunicorn_path ]; then - ynh_die "There is already a gunicorn service file at this path: $gunicorn_path " -fi +ynh_webpath_available --domain=$domain --path_url=$path_url \ + || ynh_die --message="Path not available: ${domain}${path_url}" +test ! -d $final_path \ + || ynh_die --message="There is already a directory: $final_path " -# Dependences -install_dependencies +#================================================= +# STANDARD RESTORATION STEPS +#================================================= +# RESTORE THE NGINX CONFIGURATION +#================================================= -# Restore sources & data -sudo cp -a ./sources $final_path +ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" -# Create user -useradd $app -d $final_path || echo "User already exists" +#================================================= +# RESTORE THE APP MAIN DIR +#================================================= +ynh_script_progression --message="Restoring the app main directory..." --time --weight=1 -# Set permissions -sudo chown -R $app:www-data $final_path +ynh_restore_file --origin_path="$final_path" -# Restore conf files -sudo cp -a ./nginx.conf $conf -sudo cp -a ./gunicorn.service $gunicorn_path -sudo chown root: $gunicorn_path -sudo chmod 644 $gunicorn_path +#================================================= +# RECREATE THE DEDICATED USER +#================================================= +ynh_script_progression --message="Recreating the dedicated system user..." --time --weight=1 -# Set Administrator -if ynh_user_exists $admin; then - sudo yunohost app addaccess $app -u $admin -fi +# Create the dedicated user (if not existing) +ynh_system_user_create --username=$app + +#================================================= +# RESTORE USER RIGHTS +#================================================= + +# Restore permissions on app files +chown -R $app:www-data $final_path + +#================================================= +# SPECIFIC RESTORATION +#================================================= +# REINSTALL DEPENDENCIES +#================================================= +ynh_script_progression --message="Reinstalling dependencies..." --time --weight=1 + +# Define and install dependencies +ynh_install_app_dependencies $pkg_dependencies + +#================================================= +# RESTORE THE PSQL DATABASE +#================================================= +ynh_script_progression --message="Restoring the MySQL database..." --time --weight=1 -# Restore database ynh_psql_test_if_first_run -db_name=$app -db_user=$app -ynh_psql_create_db $db_name $db_user $db_pwd -ynh_psql_execute_file_as_root "${YNH_CWD}/dump.sql" "$db_name" -# Log folder -sudo mkdir -p /var/log/$app -sudo chown -R $app /var/log/$app -sudo chgrp -R www-data /var/log/$app +db_pwd=$(ynh_app_setting_get --app=$app --key=psqlpwd) +ynh_psql_setup_db --db_user=$db_user --db_name=$db_name --db_pwd=$db_pwd +ynh_psql_connect_as --user=$db_user --password=$db_pwd --database=$db_name < ./db.sql -# Reload Nginx -sudo service nginx reload -systemctl daemon-reload -sudo systemctl start $app -sudo systemctl enable $app -sudo yunohost service add $app -l /var/log/gunicorn/$app.log +#================================================= +# RESTORE SYSTEMD +#================================================= +ynh_script_progression --message="Restoring the systemd configuration..." --time --weight=1 -ynh_app_setting_set "$app" skipped_uris "/" -sudo yunohost app ssowatconf +ynh_restore_file --origin_path="/etc/systemd/system/$app.service" +systemctl enable $app.service + +#================================================= +# ADVERTISE SERVICE IN ADMIN PANEL +#================================================= + +yunohost service add $app --log "/var/log/$app/$app.log" + +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." --time --weight=1 + +ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" + + +#================================================ +# CONFIGURE LOG DIR +#================================================ +mkdir -p /var/log/$app +chown -R $app /var/log/$app +chgrp -R www-data /var/log/$app + +#================================================= +# GENERIC FINALIZATION +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading nginx web server..." --time --weight=1 + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Restoration completed for $app" --time --last diff --git a/scripts/upgrade b/scripts/upgrade index 212a5aa..9dff0b0 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -1,75 +1,222 @@ #!/bin/bash + +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source _common.sh source /usr/share/yunohost/helpers -source common.sh -source future.sh + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." --time --weight=1 export app=$YNH_APP_INSTANCE_NAME -user=$app -export domain=$(ynh_app_setting_get $app domain) -export path=$(ynh_app_setting_get $app path) -export admin=$(ynh_app_setting_get $app admin) -export email=$(ynh_app_setting_get $app email) -export isp_name=$(ynh_app_setting_get $app isp_name) -export isp_site=$(ynh_app_setting_get $app isp_site) -export secret=$(ynh_app_setting_get $app secret) -version=$(ynh_read_json "/etc/yunohost/apps/$app/manifest.json" 'version' 2> /dev/null || echo '20170408') -last_version=$(ynh_read_manifest 'version') +export domain=$(ynh_app_setting_get --app=$app --key=domain) +export path_url=$(ynh_app_setting_get --app=$app --key=path) +export admin=$(ynh_app_setting_get --app=$app --key=admin) +export email=$(ynh_app_setting_get --app=$app --key=email) +export isp_name=$(ynh_app_setting_get --app=$app --key=isp_name) +export isp_site=$(ynh_app_setting_get --app=$app --key=isp_site) +export secret=$(ynh_app_setting_get --app=$app --key=secret) +export is_public=$(ynh_app_setting_get --app=$app --key=is_public) +export final_path=$(ynh_app_setting_get --app=$app --key=final_path) +export db_name=$(ynh_app_setting_get --app=$app --key=db_name) +export db_user=$db_name +export db_pwd=$(ynh_app_setting_get --app=$app --key=psqlpwd) -ynh_exit_if_up_to_date -ynh_check_var "$app" "app name not set" -ynh_user_exists "$admin" || err "User does not exist: $admin" -ynh_normalize_url_path "$path" +#================================================= +# CHECK VERSION +#================================================= -#if [ "${version}" = "20170408" ]; then -#fi +### This helper will compare the version of the currently installed app and the version of the upstream package. +### $upgrade_type can have 2 different values +### - UPGRADE_APP if the upstream app version has changed +### - UPGRADE_PACKAGE if only the YunoHost package has changed +### ynh_check_app_version_changed will stop the upgrade if the app is up to date. +### UPGRADE_APP should be used to upgrade the core app only if there's an upgrade to do. +upgrade_type=$(ynh_check_app_version_changed) -# Install new dependencies -install_dependencies +#================================================= +# ENSURE DOWNWARD COMPATIBILITY +#================================================= +ynh_script_progression --message="Ensuring downward compatibility..." --time --weight=1 -# Copy files to the right place -final_path=/opt/$app -[ -L ${final_path}/coin ] || ynh_setup_source $final_path +# Fix is_public as a boolean value +if [ "$is_public" = "Yes" ]; then + ynh_app_setting_set --app=$app --key=is_public --value=1 + is_public=1 +elif [ "$is_public" = "No" ]; then + ynh_app_setting_set --app=$app --key=is_public --value=0 + is_public=0 +fi -set +o nounset -source $final_path/venv/bin/activate -set -o nounset -$final_path/venv/bin/pip install -r $final_path/requirements.txt +# If db_name doesn't exist, create it +if [ -z "$db_name" ]; then + db_name=$(ynh_sanitize_dbid --db_name=$app) + ynh_app_setting_set --app=$app --key=db_name --value=$db_name +fi -# Set permissions -useradd $app -d $final_path || echo "User already exists" +# If final_path doesn't exist, create it +if [ -z "$final_path" ]; then + final_path=/opt/$app + ynh_app_setting_set --app=$app --key=final_path --value=$final_path +fi + +#================================================= +# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP +#================================================= +ynh_script_progression --message="Backing up the app before upgrading (may take a while)..." --time --weight=1 + +# Backup the current version of the app +ynh_backup_before_upgrade +ynh_clean_setup () { + # restore it if the upgrade fails + ynh_restore_upgradebackup +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# STANDARD UPGRADE STEPS +#================================================= +# STOP SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Stopping a systemd service..." --time --weight=1 + +ynh_systemd_action --service_name=$app --action="stop" --log_path="/var/log/$app/$app.log" + +#================================================= +# DOWNLOAD, CHECK AND UNPACK SOURCE +#================================================= + +if [ "$upgrade_type" == "UPGRADE_APP" ] +then + ynh_script_progression --message="Upgrading source files..." --time --weight=1 + + # Download, check integrity, uncompress and patch the source from app.src + ynh_setup_source --dest_dir="$final_path" +fi + +#================================================= +# NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Upgrading nginx web server configuration..." --time --weight=1 + +# Create a dedicated nginx config +ynh_add_nginx_config + +#================================================= +# UPGRADE DEPENDENCIES +#================================================= +ynh_script_progression --message="Upgrading dependencies..." --time --weight=1 + +ynh_install_app_dependencies $pkg_dependencies + +#================================================= +# CREATE DEDICATED USER +#================================================= +ynh_script_progression --message="Making sure dedicated system user exists..." --time --weight=1 + +# Create a dedicated user (if not existing) +ynh_system_user_create --username=$app + +#================================================= +# SPECIFIC UPGRADE +#================================================= +# CONFIGURATION DJANGO +#================================================= + +export prefix="${path_url#"/"}/" +prefix=${prefix%"/"} +ynh_backup_if_checksum_is_different --file="$final_path/app/settings_local.py" +ynh_render_template ../conf/local.py.j2 "$final_path/app/setings_local.py" +ynh_store_file_checksum --file="$final_path/app/settings_local.py" + +virtualenv "$final_path/venv" +( + set +o nounset + source "${final_path}/venv/bin/activate" + set -o nounset + + #================================================= + # PYTHON DEPENDENCIES + #================================================= + echo "django-auth-ldap<1.4" >> $final_path/requirements.txt + $final_path/venv/bin/pip install -r $final_path/requirements.txt + + #================================================= + # MIGRATE DB + #================================================= + $final_path/venv/bin/python manage.py migrate --noinput + + #================================================= + # COLLECT FILES + #================================================= + $final_path/venv/bin/python manage.py collectstatic --noinput +) + +#================================================= + +#================================================ +# UPDATE GUNICORN +#================================================ +ynh_backup_if_checksum_is_different --file="$final_path/gunicorn_config.py" +ynh_replace_string --match_string="__YNH_APP_INSTANCE_NAME__" --replace_string="$app" --target_file="../conf/gunicorn_config.py" +cp -f ../conf/gunicorn_config.py $final_path/ +ynh_store_file_checksum --file="$final_path/gunicorn_config.py" + +chown $app:www-data $final_path/gunicorn_config.py + +#================================================= +# SETUP SYSTEMD +#================================================= +ynh_script_progression --message="Upgrading systemd configuration..." --time --weight=1 + +# Create a dedicated systemd config +ynh_add_systemd_config + +#================================================= +# GENERIC FINALIZATION +#================================================= +# SECURE FILES AND DIRECTORIES +#================================================= + +# Set permissions on app files chown -R $app:www-data $final_path -pushd $final_path -if [ "${version}" = "20170731" ]; then - init_db - ynh_app_setting_delete $app mysqlpassword - $final_path/venv/bin/python manage.py dumpdata > /tmp/dump.json - - cat >> /opt/$app/coin/settings_local.py <