diff --git a/README.md b/README.md index b98d3e4..2c2071c 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,37 @@ -Wallabag v2 for Yunohost ------------------------- - -This is a work-in-progress Wallabag v2 package for YunoHost. - ---- - -**NB: Since @jeromelebleu is no longer maintaining this package, I (@lapineige) take over this repository. But I have limited time and experience, so feel free to help !** - -**Shipped version:** 2.2.2 - -[Wallabag](https://www.wallabag.org/) is a self hostable Read-It-Later application allowing -you to not miss any content anymore. Click, save, read it when you can. -It extracts content so that you can read it when you have time. - -## Features - -In addition to Wallabag core features, the following are made available with -this package: - - * Integrate with YunoHost users and SSO - i.e. logout button - * Allow one user to be the administrator (set at the installation) - * Asynchronous import using Redis (need to be enabled in the *Internal Settings*) - -## TODO - - * Write the `backup` / `restore` scripts (meanwhile please make your own backup, e.g. with the export tool) - * Refactor the application to apply for replacing wallabag v1 official application! - -## Upgrade from v1 - -The upgrade from the [Wallabag v1](https://github.com/YunoHost-Apps/wallabag_ynh) -app requires a manual operation, that's why it's provided as a new package. -For the migration process, please refer to the -[official documentation](http://doc.wallabag.org/en/master/user/import.html#id6). - -## Links - - * Report a bug: https://dev.yunohost.org/projects/apps/issues - * Wallabag website: https://www.wallabag.org/ - * YunoHost website: https://yunohost.org/ +Wallabag v2 for Yunohost +------------------------ + +This is a Wallabag v2 package for YunoHost. + +--- + +**NB: Since @jeromelebleu is no longer maintaining this package, I (@lapineige) take over this repository. But I have limited time and experience, so feel free to help !** + +**Shipped version:** 2.2.2 + +[Wallabag](https://www.wallabag.org/) is a self hostable Read-It-Later application allowing +you to not miss any content anymore. Click, save, read it when you can. +It extracts content so that you can read it when you have time. + +## Features + +In addition to Wallabag core features, the following are made available with +this package: + + * Integrate with YunoHost users and SSO - i.e. logout button + * Allow one user to be the administrator (set at the installation) + * Asynchronous import using Redis (need to be enabled in the *Internal Settings*) + + +## Upgrade from v1 + +The upgrade from the YunoHost [Wallabag v1](https://github.com/YunoHost-Apps/wallabag_ynh) +app requires a manual operation, that's why it's provided as a new package. +For the migration process, please refer to the +[Wallabag official documentation](http://doc.wallabag.org/en/master/user/import.html#id6). + +## Links + + * Report a bug: https://github.com/YunoHost-Apps/wallabag2_ynh/issues + * Wallabag website: https://www.wallabag.org/ + * YunoHost website: https://yunohost.org/ diff --git a/check_process b/check_process index 2d40931..4eafc80 100644 --- a/check_process +++ b/check_process @@ -1,5 +1,4 @@ ;; Complete test - auto_remove=1 ; Manifest domain="domain.tld" (DOMAIN) path="/path" (PATH) @@ -12,23 +11,23 @@ setup_private=0 setup_public=0 upgrade=1 - backup_restore=0 - multi_instance=0 - wrong_user=1 - wrong_path=1 + backup_restore=1 + multi_instance=1 incorrect_path=1 - corrupt_source=0 - fail_download_source=0 port_already_use=0 - final_path_already_use=0 ;;; Levels Level 1=auto Level 2=auto Level 3=auto - Level 4=0 - Level 5=auto +# https://github.com/YunoHost-Apps/wallabag2_ynh/issues/26 + Level 4=1 +# https://github.com/YunoHost-Apps/wallabag2_ynh/issues/27 + Level 5=1 Level 6=auto Level 7=auto Level 8=0 Level 9=0 Level 10=0 +;;; Options +Email= +Notification=none \ No newline at end of file diff --git a/conf/app.src b/conf/app.src new file mode 100644 index 0000000..91efecd --- /dev/null +++ b/conf/app.src @@ -0,0 +1,3 @@ +SOURCE_URL=https://static.wallabag.org/releases/wallabag-release-2.2.2.tar.gz +SOURCE_SUM=40d98bd556116dbc28f92339f0e5b93836ece87dcb01e7aaa628ea98855a1f51 +SOURCE_FORMAT=tar.gz \ No newline at end of file diff --git a/conf/nginx_sub_dir.conf b/conf/nginx.conf similarity index 67% rename from conf/nginx_sub_dir.conf rename to conf/nginx.conf index d879370..3fc9825 100644 --- a/conf/nginx_sub_dir.conf +++ b/conf/nginx.conf @@ -1,19 +1,19 @@ -location {LOCATION}/ { - alias {DESTDIR}/web/; +location __PATH__/ { + alias __FINALPATH__/web/; if ($scheme = http) { rewrite ^ https://$server_name$request_uri? permanent; } - try_files $uri @wallabag2; + try_files $uri @__NAME__; - location ~ ^{PATH}/app\.php(/|$) { + location ~ ^__PATH__/app\.php(/|$) { include fastcgi_params; fastcgi_split_path_info ^(.+\.php)(/.*)$; fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param REMOTE_USER $remote_user; - fastcgi_pass unix:/var/run/php5-fpm-{POOLNAME}.sock; + fastcgi_pass unix:/var/run/php5-fpm-__NAME__.sock; fastcgi_intercept_errors on; } @@ -27,11 +27,11 @@ location {LOCATION}/ { include conf.d/yunohost_panel.conf.inc; } -location @wallabag2 { - rewrite ^ {PATH}/app.php/$is_args$args; +location @__NAME__ { + rewrite ^ __PATH__/app.php/$is_args$args; } -location {LOCATION} { - return 301 {LOCATION}/; -} +#noroot location __PATH__ { +#noroot return 301 __PATH__/; +#noroot } diff --git a/conf/nginx_root.conf b/conf/nginx_root.conf deleted file mode 100644 index 320a21b..0000000 --- a/conf/nginx_root.conf +++ /dev/null @@ -1,32 +0,0 @@ -location {LOCATION} { - alias {DESTDIR}/web/; - - if ($scheme = http) { - rewrite ^ https://$server_name$request_uri? permanent; - } - - try_files $uri @wallabag2; - - location ~ ^{PATH}/app\.php(/|$) { - include fastcgi_params; - fastcgi_split_path_info ^(.+\.php)(/.*)$; - fastcgi_param SCRIPT_FILENAME $request_filename; - fastcgi_param PATH_INFO $fastcgi_path_info; - fastcgi_param REMOTE_USER $remote_user; - fastcgi_pass unix:/var/run/php5-fpm-{POOLNAME}.sock; - fastcgi_intercept_errors on; - } - - # return 404 for all other php files not matching the front controller - # this prevents access to other php files you don't want to be accessible. - location ~ \.php$ { - return 404; - } - - # Include SSOWAT user panel. - include conf.d/yunohost_panel.conf.inc; -} - -location @wallabag2 { - rewrite ^ {PATH}/app.php/$is_args$args; -} diff --git a/conf/parameters.yml b/conf/parameters.yml index 02aef6a..1acb3a7 100644 --- a/conf/parameters.yml +++ b/conf/parameters.yml @@ -1,6 +1,6 @@ parameters: database_driver: pdo_mysql - database_host: 127.0.0.1 + database_host: localhost database_port: 3306 database_name: {DBNAME} database_user: {DBUSER} @@ -11,7 +11,7 @@ parameters: database_charset: utf8mb4 mailer_transport: smtp - mailer_host: 127.0.0.1 + mailer_host: localhost mailer_user: null mailer_password: null diff --git a/conf/php-fpm.conf b/conf/php-fpm.conf index e249310..a5e90a4 100644 --- a/conf/php-fpm.conf +++ b/conf/php-fpm.conf @@ -1,68 +1,392 @@ -[{POOLNAME}] -; The address on which to accept FastCGI requests. -listen = /var/run/php5-fpm-{POOLNAME}.sock +; Start a new pool named 'www'. +; the variable $pool can we used in any directive and will be replaced by the +; pool name ('www' here) +[__NAMETOCHANGE__] -; Set permissions for unix socket, if one is used. +; Per pool prefix +; It only applies on the following directives: +; - 'slowlog' +; - 'listen' (unixsocket) +; - 'chroot' +; - 'chdir' +; - 'php_values' +; - 'php_admin_values' +; When not set, the global prefix (or /usr) applies instead. +; Note: This directive can also be relative to the global prefix. +; Default Value: none +;prefix = /path/to/pools/$pool + +; Unix user/group of processes +; Note: The user is mandatory. If the group is not set, the default user's group +; will be used. +user = __USER__ +group = __USER__ + +; The address on which to accept FastCGI requests. +; Valid syntaxes are: +; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific address on +; a specific port; +; 'port' - to listen on a TCP socket to all addresses on a +; specific port; +; '/path/to/unix/socket' - to listen on a unix socket. +; Note: This value is mandatory. +listen = /var/run/php5-fpm-__NAMETOCHANGE__.sock + +; Set listen(2) backlog. +; Default Value: 128 (-1 on FreeBSD and OpenBSD) +;listen.backlog = 128 + +; Set permissions for unix socket, if one is used. In Linux, read/write +; permissions must be set in order to allow connections from a web server. Many +; BSD-derived systems allow connections regardless of permissions. +; Default Values: user and group are set as the running user +; mode is set to 0660 listen.owner = www-data listen.group = www-data -listen.mode = 0600 +;listen.mode = 0660 + +; List of ipv4 addresses of FastCGI clients which are allowed to connect. +; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original +; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address +; must be separated by a comma. If this value is left blank, connections will be +; accepted from any ip address. +; Default Value: any +;listen.allowed_clients = 127.0.0.1 -; Unix user/group of processes. -user = www-data -group = www-data +; Specify the nice(2) priority to apply to the pool processes (only if set) +; The value can vary from -19 (highest priority) to 20 (lower priority) +; Note: - It will only work if the FPM master process is launched as root +; - The pool processes will inherit the master process priority +; unless it specified otherwise +; Default Value: no set +; priority = -19 ; Choose how the process manager will control the number of child processes. +; Possible Values: +; static - a fixed number (pm.max_children) of child processes; +; dynamic - the number of child processes are set dynamically based on the +; following directives. With this process management, there will be +; always at least 1 children. +; pm.max_children - the maximum number of children that can +; be alive at the same time. +; pm.start_servers - the number of children created on startup. +; pm.min_spare_servers - the minimum number of children in 'idle' +; state (waiting to process). If the number +; of 'idle' processes is less than this +; number then some children will be created. +; pm.max_spare_servers - the maximum number of children in 'idle' +; state (waiting to process). If the number +; of 'idle' processes is greater than this +; number then some children will be killed. +; ondemand - no children are created at startup. Children will be forked when +; new requests will connect. The following parameter are used: +; pm.max_children - the maximum number of children that +; can be alive at the same time. +; pm.process_idle_timeout - The number of seconds after which +; an idle process will be killed. +; Note: This value is mandatory. pm = dynamic ; The number of child processes to be created when pm is set to 'static' and the -; maximum number of child processes to be created when pm is set to 'dynamic'. -pm.max_children = 6 +; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'. +; This value sets the limit on the number of simultaneous requests that will be +; served. Equivalent to the ApacheMaxClients directive with mpm_prefork. +; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP +; CGI. The below defaults are based on a server without much resources. Don't +; forget to tweak pm.* to fit your needs. +; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand' +; Note: This value is mandatory. +pm.max_children = 10 ; The number of child processes created on startup. -pm.start_servers = 3 +; Note: Used only when pm is set to 'dynamic' +; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2 +pm.start_servers = 2 ; The desired minimum number of idle server processes. -pm.min_spare_servers = 3 +; Note: Used only when pm is set to 'dynamic' +; Note: Mandatory when pm is set to 'dynamic' +pm.min_spare_servers = 1 ; The desired maximum number of idle server processes. -pm.max_spare_servers = 5 +; Note: Used only when pm is set to 'dynamic' +; Note: Mandatory when pm is set to 'dynamic' +pm.max_spare_servers = 3 +; The number of seconds after which an idle process will be killed. +; Note: Used only when pm is set to 'ondemand' +; Default Value: 10s +;pm.process_idle_timeout = 10s; + ; The number of requests each child process should execute before respawning. +; This can be useful to work around memory leaks in 3rd party libraries. For +; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS. +; Default Value: 0 pm.max_requests = 500 ; The URI to view the FPM status page. If this value is not set, no URI will be -; recognized as a status page. -pm.status_path = /fpm-status - +; recognized as a status page. It shows the following informations: +; pool - the name of the pool; +; process manager - static, dynamic or ondemand; +; start time - the date and time FPM has started; +; start since - number of seconds since FPM has started; +; accepted conn - the number of request accepted by the pool; +; listen queue - the number of request in the queue of pending +; connections (see backlog in listen(2)); +; max listen queue - the maximum number of requests in the queue +; of pending connections since FPM has started; +; listen queue len - the size of the socket queue of pending connections; +; idle processes - the number of idle processes; +; active processes - the number of active processes; +; total processes - the number of idle + active processes; +; max active processes - the maximum number of active processes since FPM +; has started; +; max children reached - number of times, the process limit has been reached, +; when pm tries to start more children (works only for +; pm 'dynamic' and 'ondemand'); +; Value are updated in real time. +; Example output: +; pool: www +; process manager: static +; start time: 01/Jul/2011:17:53:49 +0200 +; start since: 62636 +; accepted conn: 190460 +; listen queue: 0 +; max listen queue: 1 +; listen queue len: 42 +; idle processes: 4 +; active processes: 11 +; total processes: 15 +; max active processes: 12 +; max children reached: 0 +; +; By default the status page output is formatted as text/plain. Passing either +; 'html', 'xml' or 'json' in the query string will return the corresponding +; output syntax. Example: +; http://www.foo.bar/status +; http://www.foo.bar/status?json +; http://www.foo.bar/status?html +; http://www.foo.bar/status?xml +; +; By default the status page only outputs short status. Passing 'full' in the +; query string will also return status for each pool process. +; Example: +; http://www.foo.bar/status?full +; http://www.foo.bar/status?json&full +; http://www.foo.bar/status?html&full +; http://www.foo.bar/status?xml&full +; The Full status returns for each process: +; pid - the PID of the process; +; state - the state of the process (Idle, Running, ...); +; start time - the date and time the process has started; +; start since - the number of seconds since the process has started; +; requests - the number of requests the process has served; +; request duration - the duration in µs of the requests; +; request method - the request method (GET, POST, ...); +; request URI - the request URI with the query string; +; content length - the content length of the request (only with POST); +; user - the user (PHP_AUTH_USER) (or '-' if not set); +; script - the main script called (or '-' if not set); +; last request cpu - the %cpu the last request consumed +; it's always 0 if the process is not in Idle state +; because CPU calculation is done when the request +; processing has terminated; +; last request memory - the max amount of memory the last request consumed +; it's always 0 if the process is not in Idle state +; because memory calculation is done when the request +; processing has terminated; +; If the process is in Idle state, then informations are related to the +; last request the process has served. Otherwise informations are related to +; the current request being served. +; Example output: +; ************************ +; pid: 31330 +; state: Running +; start time: 01/Jul/2011:17:53:49 +0200 +; start since: 63087 +; requests: 12808 +; request duration: 1250261 +; request method: GET +; request URI: /test_mem.php?N=10000 +; content length: 0 +; user: - +; script: /home/fat/web/docs/php/test_mem.php +; last request cpu: 0.00 +; last request memory: 0 +; +; Note: There is a real-time FPM status monitoring sample web page available +; It's available in: ${prefix}/share/fpm/status.html +; +; Note: The value must start with a leading slash (/). The value can be +; anything, but it may not be a good idea to use the .php extension or it +; may conflict with a real PHP file. +; Default Value: not set +;pm.status_path = /status + ; The ping URI to call the monitoring page of FPM. If this value is not set, no -; URI will be recognized as a ping page. -ping.path = /ping +; URI will be recognized as a ping page. This could be used to test from outside +; that FPM is alive and responding, or to +; - create a graph of FPM availability (rrd or such); +; - remove a server from a group if it is not responding (load balancing); +; - trigger alerts for the operating team (24/7). +; Note: The value must start with a leading slash (/). The value can be +; anything, but it may not be a good idea to use the .php extension or it +; may conflict with a real PHP file. +; Default Value: not set +;ping.path = /ping -; The timeout for serving a single request after which the worker process will -; be killed. -request_terminate_timeout = 1d +; This directive may be used to customize the response of a ping request. The +; response is formatted as text/plain with a 200 response code. +; Default Value: pong +;ping.response = pong +; The access log file +; Default: not set +;access.log = log/$pool.access.log + +; The access log format. +; The following syntax is allowed +; %%: the '%' character +; %C: %CPU used by the request +; it can accept the following format: +; - %{user}C for user CPU only +; - %{system}C for system CPU only +; - %{total}C for user + system CPU (default) +; %d: time taken to serve the request +; it can accept the following format: +; - %{seconds}d (default) +; - %{miliseconds}d +; - %{mili}d +; - %{microseconds}d +; - %{micro}d +; %e: an environment variable (same as $_ENV or $_SERVER) +; it must be associated with embraces to specify the name of the env +; variable. Some exemples: +; - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e +; - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e +; %f: script filename +; %l: content-length of the request (for POST request only) +; %m: request method +; %M: peak of memory allocated by PHP +; it can accept the following format: +; - %{bytes}M (default) +; - %{kilobytes}M +; - %{kilo}M +; - %{megabytes}M +; - %{mega}M +; %n: pool name +; %o: ouput header +; it must be associated with embraces to specify the name of the header: +; - %{Content-Type}o +; - %{X-Powered-By}o +; - %{Transfert-Encoding}o +; - .... +; %p: PID of the child that serviced the request +; %P: PID of the parent of the child that serviced the request +; %q: the query string +; %Q: the '?' character if query string exists +; %r: the request URI (without the query string, see %q and %Q) +; %R: remote IP address +; %s: status (response code) +; %t: server time the request was received +; it can accept a strftime(3) format: +; %d/%b/%Y:%H:%M:%S %z (default) +; %T: time the log has been written (the request has finished) +; it can accept a strftime(3) format: +; %d/%b/%Y:%H:%M:%S %z (default) +; %u: remote user +; +; Default: "%R - %u %t \"%m %r\" %s" +;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%" + +; The log file for slow requests +; Default Value: not set +; Note: slowlog is mandatory if request_slowlog_timeout is set +slowlog = /var/log/nginx/{POOLNAME}.slow.log + ; The timeout for serving a single request after which a PHP backtrace will be ; dumped to the 'slowlog' file. A value of '0s' means 'off'. +; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) +; Default Value: 0 request_slowlog_timeout = 5s - -; The log file for slow requests. -slowlog = /var/log/nginx/{POOLNAME}.slow.log - + +; The timeout for serving a single request after which the worker process will +; be killed. This option should be used when the 'max_execution_time' ini option +; does not stop script execution for some reason. A value of '0' means 'off'. +; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) +; Default Value: 0 +request_terminate_timeout = 1d + ; Set open file descriptor rlimit. -rlimit_files = 4096 - +; Default Value: system defined value +;rlimit_files = 1024 + ; Set max core size rlimit. -rlimit_core = 0 - +; Possible Values: 'unlimited' or an integer greater or equal to 0 +; Default Value: system defined value +;rlimit_core = 0 + +; Chroot to this directory at the start. This value must be defined as an +; absolute path. When this value is not set, chroot is not used. +; Note: you can prefix with '$prefix' to chroot to the pool prefix or one +; of its subdirectories. If the pool prefix is not set, the global prefix +; will be used instead. +; Note: chrooting is a great security feature and should be used whenever +; possible. However, all PHP paths will be relative to the chroot +; (error_log, sessions.save_path, ...). +; Default Value: not set +;chroot = + ; Chdir to this directory at the start. -chdir = {DESTDIR} - -; Redirect worker stdout and stderr into main error log. +; Note: relative path can be used. +; Default Value: current directory or / when chroot +chdir = __FINALPATH__ + +; Redirect worker stdout and stderr into main error log. If not set, stdout and +; stderr will be redirected to /dev/null according to FastCGI specs. +; Note: on highloaded environement, this can cause some delay in the page +; process time (several ms). +; Default Value: no catch_workers_output = yes -; Do not clear environment in FPM workers. -clear_env = no +; Limits the extensions of the main script FPM will allow to parse. This can +; prevent configuration mistakes on the web server side. You should only limit +; FPM to .php extensions to prevent malicious users to use other extensions to +; exectute php code. +; Note: set an empty value to allow all extensions. +; Default Value: .php +;security.limit_extensions = .php .php3 .php4 .php5 + +; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from +; the current environment. +; Default Value: clean env +;env[HOSTNAME] = $HOSTNAME +;env[PATH] = /usr/local/bin:/usr/bin:/bin +;env[TMP] = /tmp +;env[TMPDIR] = /tmp +;env[TEMP] = /tmp -; Additional php.ini defines, specific to this pool of workers. -; ... +; Additional php.ini defines, specific to this pool of workers. These settings +; overwrite the values previously defined in the php.ini. The directives are the +; same as the PHP SAPI: +; php_value/php_flag - you can set classic ini defines which can +; be overwritten from PHP call 'ini_set'. +; php_admin_value/php_admin_flag - these directives won't be overwritten by +; PHP call 'ini_set' +; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no. + +; Defining 'extension' will load the corresponding shared extension from +; extension_dir. Defining 'disable_functions' or 'disable_classes' will not +; overwrite previously defined php.ini values, but will append the new value +; instead. + +; Note: path INI options can be relative and will be expanded with the prefix +; (pool, global or /usr) + +; Default Value: nothing is defined by default except the values in php.ini and +; specified at startup with the -d argument +;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com +;php_flag[display_errors] = off +;php_admin_value[error_log] = /var/log/fpm-php.www.log +;php_admin_flag[log_errors] = on +;php_admin_value[memory_limit] = 32M diff --git a/conf/wallabag-deps.control b/conf/wallabag-deps.control deleted file mode 100644 index 203e0d8..0000000 --- a/conf/wallabag-deps.control +++ /dev/null @@ -1,16 +0,0 @@ -Section: misc -Priority: optional -Homepage: https://www.wallabag.org/ -Standards-Version: 3.9.2 - -Package: wallabag-deps -Version: 2.1-1 -Depends: php5-cli, php5-mysql, php5-json, php5-gd, php5-tidy, php5-curl - , php-gettext, redis-server -Architecture: all -Description: meta package for wallabag dependencies - Wallabag is a self hostable application allowing you to not miss - any content anymore. Click, save, read it when you can. It extracts - content so that you can read it when you have time. - . - This meta-package is only responsible of installing its dependencies. diff --git a/manifest.json b/manifest.json index 20862b5..2c4733c 100644 --- a/manifest.json +++ b/manifest.json @@ -10,10 +10,10 @@ "license": "MIT", "version": "2.2.2", "maintainer": { - "name": "jerome", - "email": "jerome@yunohost.org" + "name": "lapineige", + "email": "" }, - "multi_instance": false, + "multi_instance": true, "requirements": { "yunohost": ">= 2.4.0" }, diff --git a/scripts/_common.sh b/scripts/_common.sh index d0b7d08..0a1e55b 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -2,27 +2,8 @@ # Common variables # -# Wallabag version -VERSION="2.2.2" - -# Package name for Wallabag dependencies -DEPS_PKG_NAME="wallabag-deps" - -# Full Wallabag sources tarball URL -WALLABAG_SOURCE_URL="https://static.wallabag.org/releases/wallabag-release-${VERSION}.tar.gz" - -# Full Wallabag sources tarball checksum -WALLABAG_SOURCE_SHA256="40d98bd556116dbc28f92339f0e5b93836ece87dcb01e7aaa628ea98855a1f51" - -# App package root directory should be the parent folder -PKGDIR=$(cd ../; pwd) - -# -# Common helpers -# - -# Source app helpers -. /usr/share/yunohost/helpers +# Package dependencies +PKG_DEPENDENCIES="php5-cli php5-mysql php5-json php5-gd php5-tidy php5-curl php-gettext redis-server" # Execute a command as another user # usage: exec_as USER COMMAND [ARG ...] @@ -47,29 +28,45 @@ exec_console() { exec_as "$AS_USER" php "$WORKDIR/bin/console" --no-interaction --env=prod "$@" } -# Download and extract Wallabag sources to the given directory -# usage: extract_wallabag DESTDIR [AS_USER] -extract_wallabag() { - local DESTDIR=$1 - local AS_USER=${2:-$USER} - - # retrieve and extract Roundcube tarball - wb_tarball="/tmp/wallabag.tar.gz" - rm -f "$wb_tarball" - wget -q -O "$wb_tarball" "$WALLABAG_SOURCE_URL" \ - || ynh_die "Unable to download Wallabag tarball" - echo "$WALLABAG_SOURCE_SHA256 $wb_tarball" | sha256sum -c >/dev/null \ - || ynh_die "Invalid checksum of downloaded tarball" - exec_as "$AS_USER" tar xf "$wb_tarball" -C "$DESTDIR" --strip-components 1 \ - || ynh_die "Unable to extract Wallabag tarball" - rm -f "$wb_tarball" - - # apply patches - (cd "$DESTDIR" \ - && for p in ${PKGDIR}/patches/*.patch; do patch -p1 < $p; done) \ - || ynh_die "Unable to apply patches to Wallabag" +WARNING () { # Print on error output + $@ >&2 } +QUIET () { # redirect standard output to /dev/null + $@ > /dev/null +} + +HUMAN_SIZE () { # Transforms a Kb-based size to a human-readable size + human=$(numfmt --to=iec --from-unit=1K $1) + echo $human +} + +CHECK_SIZE () { # Check if enough disk space available on backup storage + file_to_analyse=$1 + backup_size=$(sudo du --summarize "$file_to_analyse" | cut -f1) + free_space=$(sudo df --output=avail "/home/yunohost.backup" | sed 1d) + + if [ $free_space -le $backup_size ] + then + WARNING echo "Not enough backup disk space for: $file_to_analyse." + WARNING echo "Space available: $(HUMAN_SIZE $free_space)" + ynh_die "Space needed: $(HUMAN_SIZE $backup_size)" + fi +} + +CHECK_DOMAINPATH () { # Check domain/path availability + sudo yunohost app checkurl $domain$path_url -a $app +} + +CHECK_FINALPATH () { # Check if destination directory already exists + final_path="/var/www/$app" + test ! -e "$final_path" || ynh_die "This path already contains a folder" +} + +#================================================= +# FUTURE YUNOHOST HELPERS - TO BE REMOVED LATER +#================================================= + # Normalize the url path syntax # Handle the slash at the beginning of path and its absence at ending # Return a normalized url path @@ -93,3 +90,521 @@ ynh_normalize_url_path () { fi echo $path_url } + +# Manage a fail of the script +# +# Print a warning to inform that the script was failed +# Execute the ynh_clean_setup function if used in the app script +# +# usage of ynh_clean_setup function +# This function provide a way to clean some residual of installation that not managed by remove script. +# To use it, simply add in your script: +# ynh_clean_setup () { +# instructions... +# } +# This function is optionnal. +# +# Usage: ynh_exit_properly is used only by the helper ynh_abort_if_errors. +# You must not use it directly. +ynh_exit_properly () { + exit_code=$? + if [ "$exit_code" -eq 0 ]; then + exit 0 # Exit without error if the script ended correctly + fi + + trap '' EXIT # Ignore new exit signals + set +eu # Do not exit anymore if a command fail or if a variable is empty + + echo -e "!!\n $app's script has encountered an error. Its execution was cancelled.\n!!" >&2 + + if type -t ynh_clean_setup > /dev/null; then # Check if the function exist in the app script. + ynh_clean_setup # Call the function to do specific cleaning for the app. + fi + + ynh_die # Exit with error status +} + +# Exit if an error occurs during the execution of the script. +# +# Stop immediatly the execution if an error occured or if a empty variable is used. +# The execution of the script is derivate to ynh_exit_properly function before exit. +# +# Usage: ynh_abort_if_errors +ynh_abort_if_errors () { + set -eu # Exit if a command fail, and if a variable is used unset. + trap ynh_exit_properly EXIT # Capturing exit signals on shell script +} + +# Define and install dependencies with a equivs control file +# This helper can/should only be called once per app +# +# usage: ynh_install_app_dependencies dep [dep [...]] +# | arg: dep - the package name to install in dependence +ynh_install_app_dependencies () { + dependencies=$@ + manifest_path="../manifest.json" + if [ ! -e "$manifest_path" ]; then + manifest_path="../settings/manifest.json" # Into the restore script, the manifest is not at the same place + fi + version=$(sudo python3 -c "import sys, json;print(json.load(open(\"$manifest_path\"))['version'])") # Retrieve the version number in the manifest file. + dep_app=${app//_/-} # Replace all '_' by '-' + + if ynh_package_is_installed "${dep_app}-ynh-deps"; then + echo "A package named ${dep_app}-ynh-deps is already installed" >&2 + else + cat > ./${dep_app}-ynh-deps.control << EOF # Make a control file for equivs-build +Section: misc +Priority: optional +Package: ${dep_app}-ynh-deps +Version: ${version} +Depends: ${dependencies// /, } +Architecture: all +Description: Fake package for ${app} (YunoHost app) dependencies + This meta-package is only responsible of installing its dependencies. +EOF + ynh_package_install_from_equivs ./${dep_app}-ynh-deps.control \ + || ynh_die "Unable to install dependencies" # Install the fake package and its dependencies + ynh_app_setting_set $app apt_dependencies $dependencies + fi +} + +# Remove fake package and its dependencies +# +# Dependencies will removed only if no other package need them. +# +# usage: ynh_remove_app_dependencies +ynh_remove_app_dependencies () { + dep_app=${app//_/-} # Replace all '_' by '-' + ynh_package_autoremove ${dep_app}-ynh-deps # Remove the fake package and its dependencies if they not still used. +} + +# Check if a mysql user exists +# +# usage: ynh_mysql_user_exists user +# | arg: user - the user for which to check existence +function ynh_mysql_user_exists() +{ + local user=$1 + if [[ -z $(ynh_mysql_execute_as_root "SELECT User from mysql.user WHERE User = '$user';") ]] + then + return 1 + else + return 0 + fi +} + +# Create a database, an user and its password. Then store the password in the app's config +# +# After executing this helper, the password of the created database will be available in $db_pwd +# It will also be stored as "mysqlpwd" into the app settings. +# +# usage: ynh_mysql_setup_db user name +# | arg: user - Owner of the database +# | arg: name - Name of the database +ynh_mysql_setup_db () { + local db_user="$1" + local db_name="$2" + db_pwd=$(ynh_string_random) # Generate a random password + ynh_mysql_create_db "$db_name" "$db_user" "$db_pwd" # Create the database + ynh_app_setting_set $app mysqlpwd $db_pwd # Store the password in the app's config +} + +# Remove a database if it exists, and the associated user +# +# usage: ynh_mysql_remove_db user name +# | arg: user - Owner of the database +# | arg: name - Name of the database +ynh_mysql_remove_db () { + local db_user="$1" + local db_name="$2" + local mysql_root_password=$(sudo cat $MYSQL_ROOT_PWD_FILE) + if mysqlshow -u root -p$mysql_root_password | grep -q "^| $db_name"; then # Check if the database exists + echo "Removing database $db_name" >&2 + ynh_mysql_drop_db $db_name # Remove the database + else + echo "Database $db_name not found" >&2 + fi + + # Remove mysql user if it exists + if $(ynh_mysql_user_exists $db_user); then + ynh_mysql_drop_user $db_user + fi +} + +# Sanitize a string intended to be the name of a database +# (More specifically : replace - and . by _) +# +# Exemple: dbname=$(ynh_sanitize_dbid $app) +# +# usage: ynh_sanitize_dbid name +# | arg: name - name to correct/sanitize +# | ret: the corrected name +ynh_sanitize_dbid () { + dbid=${1//[-.]/_} # We should avoid having - and . in the name of databases. They are replaced by _ + echo $dbid +} + +# Substitute/replace a string by another in a file +# +# usage: ynh_replace_string match_string replace_string target_file +# | arg: match_string - String to be searched and replaced in the file +# | arg: replace_string - String that will replace matches +# | arg: target_file - File in which the string will be replaced. +ynh_replace_string () { + delimit=@ + match_string=${1//${delimit}/"\\${delimit}"} # Escape the delimiter if it's in the string. + replace_string=${2//${delimit}/"\\${delimit}"} + workfile=$3 + + sudo sed --in-place "s${delimit}${match_string}${delimit}${replace_string}${delimit}g" "$workfile" +} + +# Remove a file or a directory securely +# +# usage: ynh_secure_remove path_to_remove +# | arg: path_to_remove - File or directory to remove +ynh_secure_remove () { + path_to_remove=$1 + forbidden_path=" \ + /var/www \ + /home/yunohost.app" + + if [[ "$forbidden_path" =~ "$path_to_remove" \ + # Match all paths or subpaths in $forbidden_path + || "$path_to_remove" =~ ^/[[:alnum:]]+$ \ + # Match all first level paths from / (Like /var, /root, etc...) + || "${path_to_remove:${#path_to_remove}-1}" = "/" ]] + # Match if the path finishes by /. Because it seems there is an empty variable + then + echo "Avoid deleting $path_to_remove." >&2 + else + if [ -e "$path_to_remove" ] + then + sudo rm -R "$path_to_remove" + else + echo "$path_to_remove wasn't deleted because it doesn't exist." >&2 + fi + fi +} + +# Create a system user +# +# usage: ynh_system_user_create user_name [home_dir] +# | arg: user_name - Name of the system user that will be create +# | arg: home_dir - Path of the home dir for the user. Usually the final path of the app. If this argument is omitted, the user will be created without home +ynh_system_user_create () { + if ! ynh_system_user_exists "$1" # Check if the user exists on the system + then # If the user doesn't exist + if [ $# -ge 2 ]; then # If a home dir is mentioned + user_home_dir="-d $2" + else + user_home_dir="--no-create-home" + fi + sudo useradd $user_home_dir --system --user-group $1 --shell /usr/sbin/nologin || ynh_die "Unable to create $1 system account" + fi +} + +# Delete a system user +# +# usage: ynh_system_user_delete user_name +# | arg: user_name - Name of the system user that will be create +ynh_system_user_delete () { + if ynh_system_user_exists "$1" # Check if the user exists on the system + then + echo "Remove the user $1" >&2 + sudo userdel $1 + else + echo "The user $1 was not found" >&2 + fi +} + +# Restore a previous backup if the upgrade process failed +# +# usage: +# ynh_backup_before_upgrade +# ynh_clean_setup () { +# ynh_backup_after_failed_upgrade +# } +# ynh_abort_if_errors +# +ynh_backup_after_failed_upgrade () { + echo "Upgrade failed." >&2 + app_bck=${app//_/-} # Replace all '_' by '-' + # Check if a existing backup can be found before remove and restore the application. + if sudo yunohost backup list | grep -q $app_bck-pre-upgrade$backup_number + then + # Remove the application then restore it + sudo yunohost app remove $app + # Restore the backup if the upgrade failed + sudo yunohost backup restore --ignore-hooks $app_bck-pre-upgrade$backup_number --apps $app --force + ynh_die "The app was restored to the way it was before the failed upgrade." + fi +} + +# Make a backup in case of failed upgrade +# +# usage: +# ynh_backup_before_upgrade +# ynh_clean_setup () { +# ynh_backup_after_failed_upgrade +# } +# ynh_abort_if_errors +# +ynh_backup_before_upgrade () { + backup_number=1 + old_backup_number=2 + app_bck=${app//_/-} # Replace all '_' by '-' + # Check if a backup already exist with the prefix 1. + if sudo yunohost backup list | grep -q $app_bck-pre-upgrade1 + then + # Prefix become 2 to preserve the previous backup + backup_number=2 + old_backup_number=1 + fi + + # Create another backup + sudo yunohost backup create --ignore-hooks --apps $app --name $app_bck-pre-upgrade$backup_number + if [ "$?" -eq 0 ] + then + # If the backup succedded, remove the previous backup + if sudo yunohost backup list | grep -q $app_bck-pre-upgrade$old_backup_number + then + # Remove the previous backup only if it exists + sudo yunohost backup delete $app_bck-pre-upgrade$old_backup_number > /dev/null + fi + else + ynh_die "Backup failed, the upgrade process was aborted." + fi +} + +# Create a dedicated nginx config +# +# usage: ynh_add_nginx_config +ynh_add_nginx_config () { + finalnginxconf="/etc/nginx/conf.d/$domain.d/$app.conf" + ynh_backup_if_checksum_is_different "$finalnginxconf" 1 + sudo cp ../conf/nginx.conf "$finalnginxconf" + + # To avoid a break by set -u, use a void substitution ${var:-}. If the variable is not set, it's simply set with an empty variable. + # Substitute in a nginx config file only if the variable is not empty + if test -n "${path_url:-}"; then + ynh_replace_string "__PATH__" "$path_url" "$finalnginxconf" + fi + if test -n "${domain:-}"; then + ynh_replace_string "__DOMAIN__" "$domain" "$finalnginxconf" + fi + if test -n "${port:-}"; then + ynh_replace_string "__PORT__" "$port" "$finalnginxconf" + fi + if test -n "${app:-}"; then + ynh_replace_string "__NAME__" "$app" "$finalnginxconf" + fi + if test -n "${final_path:-}"; then + ynh_replace_string "__FINALPATH__" "$final_path" "$finalnginxconf" + fi + ynh_store_file_checksum "$finalnginxconf" + + sudo systemctl reload nginx +} + +# Remove the dedicated nginx config +# +# usage: ynh_remove_nginx_config +ynh_remove_nginx_config () { + ynh_secure_remove "/etc/nginx/conf.d/$domain.d/$app.conf" + sudo systemctl reload nginx +} + +# Create a dedicated php-fpm config +# +# usage: ynh_add_fpm_config +ynh_add_fpm_config () { + finalphpconf="/etc/php5/fpm/pool.d/$app.conf" + ynh_backup_if_checksum_is_different "$finalphpconf" 1 + sudo cp ../conf/php-fpm.conf "$finalphpconf" + ynh_replace_string "__NAMETOCHANGE__" "$app" "$finalphpconf" + ynh_replace_string "__FINALPATH__" "$final_path" "$finalphpconf" + ynh_replace_string "__USER__" "$app" "$finalphpconf" + sudo chown root: "$finalphpconf" + ynh_store_file_checksum "$finalphpconf" + + if [ -e "../conf/php-fpm.ini" ] + then + finalphpini="/etc/php5/fpm/conf.d/20-$app.ini" + ynh_backup_if_checksum_is_different "$finalphpini" 1 + sudo cp ../conf/php-fpm.ini "$finalphpini" + sudo chown root: "$finalphpini" + ynh_store_file_checksum "$finalphpini" + fi + + sudo systemctl reload php5-fpm +} + +# Remove the dedicated php-fpm config +# +# usage: ynh_remove_fpm_config +ynh_remove_fpm_config () { + ynh_secure_remove "/etc/php5/fpm/pool.d/$app.conf" + ynh_secure_remove "/etc/php5/fpm/conf.d/20-$app.ini" 2>&1 + sudo systemctl reload php5-fpm +} + +# Calculate and store a file checksum into the app settings +# +# $app should be defined when calling this helper +# +# usage: ynh_store_file_checksum file +# | arg: file - The file on which the checksum will performed, then stored. +ynh_store_file_checksum () { + local checksum_setting_name=checksum_${1//[\/ ]/_} # Replace all '/' and ' ' by '_' + ynh_app_setting_set $app $checksum_setting_name $(sudo md5sum "$1" | cut -d' ' -f1) +} + +# Verify the checksum and backup the file if it's different +# This helper is primarily meant to allow to easily backup personalised/manually +# modified config files. +# +# $app should be defined when calling this helper +# +# usage: ynh_backup_if_checksum_is_different file [compress] +# | arg: file - The file on which the checksum test will be perfomed. +# | arg: compress - 1 to compress the backup instead of a simple copy +# A compression is needed for a file which will be analyzed even if its name is different. +# +# | ret: Return the name a the backup file, or nothing +ynh_backup_if_checksum_is_different () { + local file=$1 + local compress_backup=${2:-0} # If $2 is empty, compress_backup will set at 0 + local checksum_setting_name=checksum_${file//[\/ ]/_} # Replace all '/' and ' ' by '_' + local checksum_value=$(ynh_app_setting_get $app $checksum_setting_name) + if [ -n "$checksum_value" ] + then # Proceed only if a value was stored into the app settings + if ! echo "$checksum_value $file" | sudo md5sum -c --status + then # If the checksum is now different + backup_file="$file.backup.$(date '+%d.%m.%y_%Hh%M,%Ss')" + if [ $compress_backup -eq 1 ] + then + sudo tar --create --gzip --file "$backup_file.tar.gz" "$file" # Backup the current file and compress + backup_file="$backup_file.tar.gz" + else + sudo cp -a "$file" "$backup_file" # Backup the current file + fi + echo "File $file has been manually modified since the installation or last upgrade. So it has been duplicated in $backup_file" >&2 + echo "$backup_file" # Return the name of the backup file + fi + fi +} + +YNH_EXECUTION_DIR=$(pwd) +# Download, check integrity, uncompress and patch the source from app.src +# +# The file conf/app.src need to contains: +# +# SOURCE_URL=Address to download the app archive +# SOURCE_SUM=Control sum +# # (Optional) Programm to check the integrity (sha256sum, md5sum$YNH_EXECUTION_DIR/...) +# # default: sha256 +# SOURCE_SUM_PRG=sha256 +# # (Optional) Archive format +# # default: tar.gz +# SOURCE_FORMAT=tar.gz +# # (Optional) Put false if source are directly in the archive root +# # default: true +# SOURCE_IN_SUBDIR=false +# # (Optionnal) Name of the local archive (offline setup support) +# # default: ${src_id}.${src_format} +# SOURCE_FILENAME=example.tar.gz +# +# Details: +# This helper download sources from SOURCE_URL if there is no local source +# archive in /opt/yunohost-apps-src/APP_ID/SOURCE_FILENAME +# +# Next, it check the integrity with "SOURCE_SUM_PRG -c --status" command. +# +# If it's ok, the source archive will be uncompress in $dest_dir. If the +# SOURCE_IN_SUBDIR is true, the first level directory of the archive will be +# removed. +# +# Finally, patches named sources/patches/${src_id}-*.patch and extra files in +# sources/extra_files/$src_id will be applyed to dest_dir +# +# +# usage: ynh_setup_source dest_dir [source_id] +# | arg: dest_dir - Directory where to setup sources +# | arg: source_id - Name of the app, if the package contains more than one app +ynh_setup_source () { + local dest_dir=$1 + local src_id=${2:-app} # If the argument is not given, source_id equal "app" + + # Load value from configuration file (see above for a small doc about this file + # format) + local src_url=$(grep 'SOURCE_URL=' "$YNH_EXECUTION_DIR/../conf/${src_id}.src" | cut -d= -f2-) + local src_sum=$(grep 'SOURCE_SUM=' "$YNH_EXECUTION_DIR/../conf/${src_id}.src" | cut -d= -f2-) + local src_sumprg=$(grep 'SOURCE_SUM_PRG=' "$YNH_EXECUTION_DIR/../conf/${src_id}.src" | cut -d= -f2-) + local src_format=$(grep 'SOURCE_FORMAT=' "$YNH_EXECUTION_DIR/../conf/${src_id}.src" | cut -d= -f2-) + local src_in_subdir=$(grep 'SOURCE_IN_SUBDIR=' "$YNH_EXECUTION_DIR/../conf/${src_id}.src" | cut -d= -f2-) + local src_filename=$(grep 'SOURCE_FILENAME=' "$YNH_EXECUTION_DIR/../conf/${src_id}.src" | cut -d= -f2-) + + # Default value + src_sumprg=${src_sumprg:-sha256sum} + src_in_subdir=${src_in_subdir:-true} + src_format=${src_format:-tar.gz} + src_format=$(echo "$src_format" | tr '[:upper:]' '[:lower:]') + if [ "$src_filename" = "" ] ; then + src_filename="${src_id}.${src_format}" + fi + local local_src="/opt/yunohost-apps-src/${YNH_APP_ID}/${src_filename}" + + if test -e "$local_src" + then # Use the local source file if it is present + cp $local_src $src_filename + else # If not, download the source + wget -nv -O $src_filename $src_url + fi + + # Check the control sum + echo "${src_sum} ${src_filename}" | ${src_sumprg} -c --status \ + || ynh_die "Corrupt source" + + # Extract source into the app dir + mkdir -p "$dest_dir" + if [ "$src_format" = "zip" ] + then + # Zip format + # Using of a temp directory, because unzip doesn't manage --strip-components + if $src_in_subdir ; then + local tmp_dir=$(mktemp -d) + unzip -quo $src_filename -d "$tmp_dir" + cp -a $tmp_dir/*/. "$dest_dir" + ynh_secure_remove "$tmp_dir" + else + unzip -quo $src_filename -d "$dest_dir" + fi + else + local strip="" + if $src_in_subdir ; then + strip="--strip-components 1" + fi + if [[ "$src_format" =~ ^tar.gz|tar.bz2|tar.xz$ ]] ; then + tar -xf $src_filename -C "$dest_dir" $strip + else + ynh_die "Archive format unrecognized." + fi + fi + + # Apply patches + if (( $(find $YNH_EXECUTION_DIR/../sources/patches/ -type f -name "${src_id}-*.patch" 2> /dev/null | wc -l) > "0" )); then + local old_dir=$(pwd) + (cd "$dest_dir" \ + && for p in $YNH_EXECUTION_DIR/../sources/patches/${src_id}-*.patch; do \ + patch -p1 < $p; done) \ + || ynh_die "Unable to apply patches" + cd $old_dir + fi + + # Add supplementary files + if test -e "$YNH_EXECUTION_DIR/../sources/extra_files/${src_id}"; then + cp -a $YNH_EXECUTION_DIR/../sources/extra_files/$src_id/. "$dest_dir" + fi + +} \ No newline at end of file diff --git a/scripts/backup b/scripts/backup new file mode 100644 index 0000000..81ca5dd --- /dev/null +++ b/scripts/backup @@ -0,0 +1,55 @@ +#!/bin/bash + +# Exit on command errors and treat unset variables as an error +set -eu + +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +if [ ! -e _common.sh ]; then + # Fetch helpers file if not in current directory + sudo cp ../settings/scripts/_common.sh ./_common.sh + sudo chmod a+rx _common.sh +fi +source _common.sh +source /usr/share/yunohost/helpers + +#================================================= +# LOAD SETTINGS +#================================================= + +app=$YNH_APP_INSTANCE_NAME + +domain=$(ynh_app_setting_get $app domain) +final_path="/var/www/${app}" +db_name=$(ynh_app_setting_get $app db_name) + +#================================================= +# STANDARD BACKUP STEPS +#================================================= +# BACKUP APP MAIN DIR +#================================================= + +CHECK_SIZE "$final_path" +ynh_backup "$final_path" "sources" + +#================================================= +# BACKUP NGINX CONFIGURATION +#================================================= + +ynh_backup "/etc/nginx/conf.d/$domain.d/$app.conf" "nginx.conf" + +#================================================= +# BACKUP PHP-FPM CONFIGURATION +#================================================= + +ynh_backup "/etc/php5/fpm/pool.d/$app.conf" "php-fpm.conf" + +#================================================= +# BACKUP MYSQL DB +#================================================= + +ynh_mysql_dump_db "$db_name" > dump.sql +CHECK_SIZE "dump.sql" +ynh_backup "dump.sql" "db.sql" \ No newline at end of file diff --git a/scripts/install b/scripts/install index 7d33c0d..8947b94 100644 --- a/scripts/install +++ b/scripts/install @@ -1,105 +1,147 @@ #!/bin/bash -# Exit on command errors and treat unset variables as an error -set -eu +#================================================= +# GENERIC STARTING +#================================================= +# IMPORT GENERIC HELPERS +#================================================= -# Load common variables and helpers -source ./_common.sh +source _common.sh +source /usr/share/yunohost/helpers + +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= + +ynh_abort_if_errors # Stop script if an error is detected + +#================================================= +# RETRIEVE ARGUMENTS FROM THE MANIFEST +#================================================= # Retrieve app id app=$YNH_APP_INSTANCE_NAME # Retrieve arguments domain=$YNH_APP_ARG_DOMAIN -path=$(ynh_normalize_url_path $YNH_APP_ARG_PATH) +path_url=$YNH_APP_ARG_PATH admin=$YNH_APP_ARG_ADMIN -# Set app specific variables -dbname=$app -dbuser=$app +#================================================= +# CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS +#================================================= -# Check domain/path availability -sudo yunohost app checkurl "${domain}${path}" -a "$app" \ - || exit 1 +path_url=$(ynh_normalize_url_path $path_url) # Check and normalize path +CHECK_DOMAINPATH # Check domain and path availability +CHECK_FINALPATH # Check if destination directory is not already in use -# Check admin user parameter -ynh_user_exists "$admin" \ - || ynh_die "The chosen admin user does not exist" -ynh_app_setting_set "$app" admin_user "$admin" +#================================================= +# STORE SETTINGS FROM MANIFEST +#================================================= -# Check destination directory -DESTDIR="/var/www/${app}" -[[ -d "$DESTDIR" ]] && ynh_die \ -"The destination directory '${DESTDIR}' already exists.\ - You should safely delete it before installing this app." +ynh_app_setting_set $app domain "$domain" +ynh_app_setting_set $app path_url "$path_url" +ynh_app_setting_set $app admin "$admin" -# Install dependencies -ynh_package_install_from_equivs ../conf/${DEPS_PKG_NAME}.control \ - || ynh_die "Unable to install dependencies" +#================================================= +# STANDARD MODIFICATIONS +#================================================= +# INSTALL DEPENDENCIES +#================================================= -# Create tmp directory and fetch app inside -TMPDIR=$(ynh_mkdir_tmp) -extract_wallabag "$TMPDIR" +ynh_install_app_dependencies "$PKG_DEPENDENCIES" + +#================================================= +# CREATE A MYSQL DB +#================================================= + +db_name=$(ynh_sanitize_dbid $app) +db_user="$db_name" # Generate random DES key & password deskey=$(ynh_string_random 24) -dbpass=$(ynh_string_random) -ynh_app_setting_set "$app" mysqlpwd "$dbpass" ynh_app_setting_set "$app" deskey "$deskey" +ynh_app_setting_set "$app" db_name "$db_name" # Initialize database -ynh_mysql_create_db "$dbname" "$dbuser" "$dbpass" +ynh_mysql_setup_db "$db_user" "$db_name" +#================================================= +# DOWNLOAD, CHECK AND UNPACK SOURCE +#================================================= + +ynh_app_setting_set $app final_path "$final_path" +# Create tmp directory and fetch app inside +TMPDIR=$(mktemp -d) +ynh_setup_source "$TMPDIR" + +#================================================= +# CREATE DEDICATED USER +#================================================= + +ynh_system_user_create $app # Create a dedicated system user + +#================================================= +# SPECIFIC SETUP +#================================================= # Copy and set Wallabag dist configuration wb_conf="${TMPDIR}/app/config/parameters.yml" cp ../conf/parameters.yml "$wb_conf" -sed -i "s@{DBNAME}@${dbname}@g" "$wb_conf" -sed -i "s@{DBUSER}@${dbuser}@g" "$wb_conf" -sed -i "s@{DBPASS}@${dbpass}@g" "$wb_conf" -sed -i "s@{DESKEY}@${deskey}@g" "$wb_conf" +ynh_replace_string "{DBNAME}" "${db_name}" "$wb_conf" +ynh_replace_string "{DBUSER}" "${db_user}" "$wb_conf" +ynh_replace_string "{DBPASS}" "${db_pwd}" "$wb_conf" +ynh_replace_string "{DESKEY}" "${deskey}" "$wb_conf" # Install files and set permissions -sudo mv "$TMPDIR" "$DESTDIR" +sudo mv "$TMPDIR" "$final_path" -cd $DESTDIR -sudo chown -R www-data: "$DESTDIR" +# Set rights on directory +sudo chown -R $app: $final_path +sudo chmod 755 $final_path # Install dependencies and Wallabag -exec_console www-data "$DESTDIR" wallabag:install +exec_console $app "$final_path" wallabag:install # Add users to Wallabag for username in $(ynh_user_list); do user_email=$(sudo yunohost user info "$username" --output-as plain \ | ynh_get_plain_key mail) user_pass=$(ynh_string_random) - exec_console www-data "$DESTDIR" fos:user:create \ + exec_console $app "$final_path" fos:user:create \ "$username" "$user_email" "$user_pass" done # Set admin user -exec_console www-data "$DESTDIR" fos:user:promote --super "$admin" +exec_console $app "$final_path" fos:user:promote --super "$admin" -# Copy and set nginx configuration -if [[ "$path" == "/" ]] ; then - nginx_conf=$PKGDIR/conf/nginx_root.conf +# Configure Wallabag instance URL +ynh_mysql_connect_as "$db_name" "$db_pwd" "$db_user" <<< "UPDATE craue_config_setting SET value = 'https://$domain$path_url' WHERE name = 'wallabag_url'" + +#================================================= +# NGINX CONFIGURATION +#================================================= + +ynh_add_nginx_config +if [ "$path_url" = "/" ] +then + # Remove prefix on #noroot lines + sudo sed --in-place '/#noroot*/d' /etc/nginx/conf.d/$domain.d/$app.conf + # Replace "//" location (due to nginx template) + ynh_replace_string " // " " / " /etc/nginx/conf.d/$domain.d/$app.conf else - nginx_conf=$PKGDIR/conf/nginx_sub_dir.conf + # Remove #noroot lines + ynh_replace_string "#noroot" "" /etc/nginx/conf.d/$domain.d/$app.conf fi -sed -i "s@{LOCATION}@${path:-/}@g" "$nginx_conf" -sed -i "s@{PATH}@${path}@g" "$nginx_conf" -sed -i "s@{DESTDIR}@${DESTDIR}@g" "$nginx_conf" -sed -i "s@{POOLNAME}@${app}@g" "$nginx_conf" -sudo cp "$nginx_conf" "/etc/nginx/conf.d/${domain}.d/${app}.conf" +ynh_store_file_checksum "/etc/nginx/conf.d/$domain.d/$app.conf" # Copy and set php-fpm configuration -phpfpm_conf="/etc/php5/fpm/pool.d/${app}.conf" -sed -i "s@{POOLNAME}@${app}@g" $PKGDIR/conf/php-fpm.conf -sed -i "s@{DESTDIR}@${DESTDIR}/@g" $PKGDIR/conf/php-fpm.conf -sudo cp $PKGDIR/conf/php-fpm.conf "$phpfpm_conf" +ynh_add_fpm_config # Set SSOwat rules ynh_app_setting_set "$app" unprotected_uris "/" -# Reload services -sudo service php5-fpm restart -sudo service nginx reload +#================================================= +# RELOAD NGINX +#================================================= +sudo systemctl restart php5-fpm +sudo systemctl reload nginx diff --git a/scripts/remove b/scripts/remove index d58654b..8a942e1 100644 --- a/scripts/remove +++ b/scripts/remove @@ -1,30 +1,67 @@ #!/bin/bash -# Retrieve app id +# Treat unset variables as an error +set -u +#================================================= +# GENERIC STARTING +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +source _common.sh +source /usr/share/yunohost/helpers + +#================================================= +# LOAD SETTINGS +#================================================= + app=$YNH_APP_INSTANCE_NAME -# Load common variables and helpers -. ./_common.sh - -# Set app specific variables -dbname=$app -dbuser=$app - -# Drop MySQL database and user -ynh_mysql_drop_db "$dbname" 2>/dev/null || true -ynh_mysql_drop_user "$dbuser" 2>/dev/null || true - -# Retrieve domain from app settings +domain=$(ynh_app_setting_get $app domain) +db_name=$(ynh_app_setting_get $app db_name) domain=$(ynh_app_setting_get "$app" domain) -# Delete app directory and configurations -sudo rm -rf "/var/www/${app}" -sudo rm -f "/etc/php5/fpm/pool.d/${app}.conf" -[[ -n $domain ]] && sudo rm -f "/etc/nginx/conf.d/${domain}.d/${app}.conf" +#================================================= +# STANDARD REMOVE +#================================================= +# REMOVE DEPENDENCIES +#================================================= + +ynh_remove_app_dependencies + +#================================================= +# REMOVE THE MYSQL DB +#================================================= + +ynh_mysql_remove_db "$app" "$db_name" + +#================================================= +# REMOVE APP MAIN DIR +#================================================= + +ynh_secure_remove "/var/www/$app" + +#================================================= +# REMOVE NGINX AND PHP-FPM CONFIGURATION +#================================================= + +ynh_remove_fpm_config +ynh_remove_nginx_config # Reload services -sudo service php5-fpm restart || true -sudo service nginx reload || true +sudo systemctl restart php5-fpm +sudo systemctl reload nginx -# Remove app dependencies -ynh_package_autoremove "$DEPS_PKG_NAME" || true +#================================================= +# REMOVE DEPENDENCIES +#================================================= +ynh_remove_app_dependencies +# The following command is keeped as a matter of transition with the previous way +# of managing dependencies +ynh_package_autoremove "wallabag-deps" || true + +#================================================= +# REMOVE DEDICATED USER +#================================================= + +ynh_system_user_delete $app \ No newline at end of file diff --git a/scripts/restore b/scripts/restore new file mode 100644 index 0000000..4f717de --- /dev/null +++ b/scripts/restore @@ -0,0 +1,90 @@ +#!/bin/bash + +# Exit on command errors and treat unset variables as an error +set -eu + +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +if [ ! -e _common.sh ]; then + # Fetch helpers file if not in current directory + sudo cp ../settings/scripts/_common.sh ./_common.sh + sudo chmod a+rx _common.sh +fi +source _common.sh +source /usr/share/yunohost/helpers + +#================================================= +# LOAD SETTINGS +#================================================= + +app=$YNH_APP_INSTANCE_NAME + +domain=$(ynh_app_setting_get $app domain) +path_url=$(ynh_app_setting_get $app path) +is_public=$(ynh_app_setting_get $app is_public) +final_path=$(ynh_app_setting_get $app final_path) +db_name=$(ynh_app_setting_get $app db_name) + +#================================================= +# CHECK IF THE APP CAN BE RESTORED +#================================================= + +CHECK_DOMAINPATH # Check domain and path availability +CHECK_FINALPATH # Check if destination directory is not already in use + +#================================================= +# INSTALL DEPENDENCIES +#================================================= + +ynh_install_app_dependencies "$PKG_DEPENDENCIES" + +#================================================= +# STANDARD RESTORE STEPS +#================================================= +# RESTORE NGINX CONFIGURATION +#================================================= + +sudo cp -a ./nginx.conf /etc/nginx/conf.d/$domain.d/$app.conf + +#================================================= +# RESTORE APP MAIN DIR +#================================================= + +sudo cp -a ./sources/. $final_path + +#================================================= +# RESTORE MYSQL DB +#================================================= + +db_pwd=$(ynh_app_setting_get $app mysqlpwd) +ynh_mysql_create_db $db_name $db_name $db_pwd +ynh_mysql_connect_as $db_name $db_pwd $db_name < ./db.sql + +#================================================= +# RECREATE OF THE DEDICATED USER +#================================================= + +ynh_system_user_create $app # Recreate the dedicated user, if not existing + +#================================================= +# RESTORE USER RIGHTS +#================================================= + +sudo chown -R $app: $final_path + +#================================================= +# RESTORE PHP-FPM CONFIGURATION +#================================================= + +sudo cp -a ./php-fpm.conf /etc/php5/fpm/pool.d/$app.conf + +#================================================= +# GENERIC FINALIZATION +#================================================= +# RELOAD NGINX AND PHP-FPM +#================================================= + +sudo systemctl reload php5-fpm +sudo systemctl reload nginx diff --git a/scripts/upgrade b/scripts/upgrade index aaf1a03..4cc5529 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -2,20 +2,20 @@ # Exit on command errors and treat unset variables as an error set -eu +#================================================= +# GENERIC STARTING +#================================================= +# IMPORT GENERIC HELPERS +#================================================= -# Load common variables and helpers -source ./_common.sh +source _common.sh +source /usr/share/yunohost/helpers +#================================================= +# LOAD SETTINGS +#================================================= # Set app specific variables app=$YNH_APP_INSTANCE_NAME -dbname=$app -dbuser=$app - -# Retrieve arguments -domain=$(ynh_app_setting_get "$app" domain) -path=$(ynh_normalize_url_path $(ynh_app_setting_get "$app" path)) -dbpass=$(ynh_app_setting_get "$app" mysqlpwd) -deskey=$(ynh_app_setting_get "$app" deskey) # Check destination directory DESTDIR="/var/www/$app" @@ -23,52 +23,117 @@ DESTDIR="/var/www/$app" "The destination directory '$DESTDIR' does not exist.\ The app is not correctly installed, you should remove it first." -# Install dependencies -ynh_package_install_from_equivs ../conf/${DEPS_PKG_NAME}.control \ - || ynh_die "Unable to install dependencies" +# Retrieve arguments +domain=$(ynh_app_setting_get "$app" domain) +path_url=$(ynh_app_setting_get "$app" path_url) +# Compatibility with previous version +if [ -z "$path_url" ] ; then + path_url=$(ynh_app_setting_get "$app" path) + ynh_app_setting_set $app path_url "$path_url" +fi +path_url=$(ynh_normalize_url_path $path_url) +db_pwd=$(ynh_app_setting_get "$app" mysqlpwd) +deskey=$(ynh_app_setting_get "$app" deskey) +final_path=$(ynh_app_setting_get "$app" final_path) +# Compatibility with previous version +if [ -z "$final_path" ] ; then + final_path="/var/www/$app" + ynh_app_setting_set $app final_path "$final_path" +fi + +db_name=$(ynh_app_setting_get "$app" db_name) +# Compatibility with previous version +if [ -z "$db_name" ] ; then + db_name=$app + ynh_app_setting_set "$app" db_name "$db_name" +fi +db_user="$db_name" + +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= + +# Use prior backup and restore on error only if backup feature +# exists on installed instance +if [ -f "/etc/yunohost/apps/$app/scripts/backup" ] ; then + ynh_backup_before_upgrade # Backup the current version of the app + ynh_clean_setup () { + ynh_backup_after_failed_upgrade + } + ynh_abort_if_errors # Stop script if an error is detected +fi + +#================================================= +# INSTALL DEPENDENCIES +#================================================= + +ynh_install_app_dependencies "$PKG_DEPENDENCIES" + +#================================================= +# DOWNLOAD, CHECK AND UNPACK SOURCE +#================================================= # Create tmp directory and fetch app inside TMPDIR=$(ynh_mkdir_tmp) -extract_wallabag "$TMPDIR" +ynh_setup_source "$TMPDIR" + +#================================================= +# CREATE DEDICATED USER +#================================================= + +ynh_system_user_create $app # Create dedicated user if not existing + +#================================================= +# SPECIFIC SETUP +#================================================= # Copy and set Wallabag dist configuration wb_conf="${TMPDIR}/app/config/parameters.yml" cp ../conf/parameters.yml "$wb_conf" -sed -i "s@{DBNAME}@${dbname}@g" "$wb_conf" -sed -i "s@{DBUSER}@${dbuser}@g" "$wb_conf" -sed -i "s@{DBPASS}@${dbpass}@g" "$wb_conf" -sed -i "s@{DESKEY}@${deskey}@g" "$wb_conf" +ynh_replace_string "{DBNAME}" "${db_name}" "$wb_conf" +ynh_replace_string "{DBUSER}" "${db_user}" "$wb_conf" +ynh_replace_string "{DBPASS}" "${db_pwd}" "$wb_conf" +ynh_replace_string "{DESKEY}" "${deskey}" "$wb_conf" # Replace files and set permissions -sudo rm -rf "$DESTDIR" -sudo mv "$TMPDIR" "$DESTDIR" -sudo chown -R www-data: "$DESTDIR" +ynh_secure_remove "${final_path}/var/cache" +sudo mkdir "${final_path}/var/cache" +sudo rsync -a $TMPDIR/* "${final_path}" +sudo chown -R $app: "${final_path}" +sudo chmod 755 $final_path # Upgrade database and clear the cache -exec_console www-data "$DESTDIR" doctrine:migrations:migrate -exec_console www-data "$DESTDIR" cache:clear +exec_console $app "${final_path}" doctrine:migrations:migrate +exec_console $app "${final_path}" cache:clear -# Copy and set nginx configuration -if [[ "$path" == "/" ]] ; then - nginx_conf=$PKGDIR/conf/nginx_root.conf +# Configure Wallabag instance URL +ynh_mysql_connect_as "$db_name" "$db_pwd" "$db_user" <<< "UPDATE craue_config_setting SET value = 'https://$domain$path_url' WHERE name = 'wallabag_url'" + +#================================================= +# NGINX CONFIGURATION +#================================================= + +ynh_add_nginx_config +if [ "$path_url" = "/" ] +then + # Remove prefix on #noroot lines + sudo sed --in-place '/#noroot*/d' /etc/nginx/conf.d/$domain.d/$app.conf + # Replace "//" location (due to nginx template) + ynh_replace_string " // " " / " /etc/nginx/conf.d/$domain.d/$app.conf else - nginx_conf=$PKGDIR/conf/nginx_sub_dir.conf + # Remove #noroot lines + ynh_replace_string "#noroot" "" /etc/nginx/conf.d/$domain.d/$app.conf fi -sed -i "s@{LOCATION}@${path:-/}@g" "$nginx_conf" -sed -i "s@{PATH}@${path}@g" "$nginx_conf" -sed -i "s@{DESTDIR}@${DESTDIR}@g" "$nginx_conf" -sed -i "s@{POOLNAME}@${app}@g" "$nginx_conf" -sudo cp "$nginx_conf" "/etc/nginx/conf.d/${domain}.d/${app}.conf" +ynh_store_file_checksum "/etc/nginx/conf.d/$domain.d/$app.conf" # Copy and set php-fpm configuration -phpfpm_conf="/etc/php5/fpm/pool.d/${app}.conf" -sed -i "s@{POOLNAME}@${app}@g" ../conf/php-fpm.conf -sed -i "s@{DESTDIR}@${DESTDIR}/@g" ../conf/php-fpm.conf -sudo cp ../conf/php-fpm.conf "$phpfpm_conf" +ynh_add_fpm_config # Set SSOwat rules ynh_app_setting_set "$app" unprotected_uris "/" -# Reload services -sudo service php5-fpm restart -sudo service nginx reload +#================================================= +# RELOAD NGINX +#================================================= +sudo systemctl restart php5-fpm +sudo systemctl reload nginx \ No newline at end of file diff --git a/patches/00-ldap-auth.patch b/sources/patches/app-00-ldap-auth.patch similarity index 97% rename from patches/00-ldap-auth.patch rename to sources/patches/app-00-ldap-auth.patch index 2b894d6..f458191 100644 --- a/patches/00-ldap-auth.patch +++ b/sources/patches/app-00-ldap-auth.patch @@ -1,37 +1,37 @@ ---- a/app/config/services.yml 2016-05-25 18:09:56.374914445 +0200 -+++ b/app/config/services.yml 2016-05-25 18:07:38.775042951 +0200 -@@ -36,3 +36,7 @@ - arguments: ["@session"] - tags: - - { name: kernel.event_listener, event: security.interactive_login, method: onInteractiveLogin } -+ -+ yunohost.ldap: -+ class: Symfony\Component\Ldap\LdapClient -+ arguments: ["localhost"] ---- a/app/config/security.yml 2016-05-25 18:09:46.814645164 +0200 -+++ b/app/config/security.yml 2016-05-25 18:07:38.775042951 +0200 -@@ -11,6 +11,14 @@ - entity: { class: WallabagUserBundle:User, property: username } - fos_userbundle: - id: fos_user.user_provider.username -+ yunohost_users: -+ ldap: -+ service: yunohost.ldap -+ base_dn: ou=users,dc=yunohost,dc=org -+ search_dn: -+ search_password: -+ filter: (&(uid={username})(objectClass=posixAccount)) -+ default_roles: ROLE_USER - - # the main part of the security, where you can set up firewalls - # for specific sections of your app -@@ -36,6 +44,9 @@ - - secured_area: - pattern: ^/ -+ http_basic_ldap: -+ service: yunohost.ldap -+ dn_string: "uid={username},ou=users,dc=yunohost,dc=org" - form_login: - provider: fos_userbundle - csrf_token_generator: security.csrf.token_manager +--- a/app/config/services.yml 2016-05-25 18:09:56.374914445 +0200 ++++ b/app/config/services.yml 2016-05-25 18:07:38.775042951 +0200 +@@ -36,3 +36,7 @@ + arguments: ["@session"] + tags: + - { name: kernel.event_listener, event: security.interactive_login, method: onInteractiveLogin } ++ ++ yunohost.ldap: ++ class: Symfony\Component\Ldap\LdapClient ++ arguments: ["localhost"] +--- a/app/config/security.yml 2016-05-25 18:09:46.814645164 +0200 ++++ b/app/config/security.yml 2016-05-25 18:07:38.775042951 +0200 +@@ -11,6 +11,14 @@ + entity: { class: WallabagUserBundle:User, property: username } + fos_userbundle: + id: fos_user.user_provider.username ++ yunohost_users: ++ ldap: ++ service: yunohost.ldap ++ base_dn: ou=users,dc=yunohost,dc=org ++ search_dn: ++ search_password: ++ filter: (&(uid={username})(objectClass=posixAccount)) ++ default_roles: ROLE_USER + + # the main part of the security, where you can set up firewalls + # for specific sections of your app +@@ -36,6 +44,9 @@ + + secured_area: + pattern: ^/ ++ http_basic_ldap: ++ service: yunohost.ldap ++ dn_string: "uid={username},ou=users,dc=yunohost,dc=org" + form_login: + provider: fos_userbundle + csrf_token_generator: security.csrf.token_manager diff --git a/patches/01-logout-success-handler.patch b/sources/patches/app-01-logout-success-handler.patch similarity index 97% rename from patches/01-logout-success-handler.patch rename to sources/patches/app-01-logout-success-handler.patch index 1b7a6d9..a3e75fc 100644 --- a/patches/01-logout-success-handler.patch +++ b/sources/patches/app-01-logout-success-handler.patch @@ -1,60 +1,60 @@ -diff --git a/app/config/security.yml b/app/config/security.yml -index b07b509..62f2550 100644 ---- a/app/config/security.yml -+++ b/app/config/security.yml -@@ -60,7 +60,7 @@ security: - - logout: - path: /logout -- target: / -+ success_handler: yunohost.logout_success_handler - - access_control: - - { path: ^/api/doc, roles: IS_AUTHENTICATED_ANONYMOUSLY } -diff --git a/app/config/services.yml b/app/config/services.yml -index 8a09fde..ee63e06 100644 ---- a/app/config/services.yml -+++ b/app/config/services.yml -@@ -37,6 +37,9 @@ services: - tags: - - { name: kernel.event_listener, event: security.interactive_login, method: onInteractiveLogin } - -+ yunohost.logout_success_handler: -+ class: Wallabag\YunoHostBundle\Security\LogoutSuccessHandler -+ - yunohost.ldap: - class: Symfony\Component\Ldap\LdapClient - arguments: ["localhost"] -diff --git a/src/Wallabag/YunoHostBundle/Security/LogoutSuccessHandler.php b/src/Wallabag/YunoHostBundle/Security/LogoutSuccessHandler.php -new file mode 100644 -index 0000000..b326824 ---- /dev/null -+++ b/src/Wallabag/YunoHostBundle/Security/LogoutSuccessHandler.php -@@ -0,0 +1,27 @@ -+