From 0cc20fb19c1b973950bc0d6c3c899ab9ca2a19f0 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Mon, 16 Nov 2020 19:12:12 +0100 Subject: [PATCH 01/25] Small fixes --- check_process | 13 ----- conf/nginx.conf | 6 ++- manifest.json | 12 ++--- scripts/_common.sh | 120 ++++++--------------------------------------- scripts/install | 113 ++++++++++++------------------------------ 5 files changed, 55 insertions(+), 209 deletions(-) diff --git a/check_process b/check_process index 0cbeae3..9bc4859 100644 --- a/check_process +++ b/check_process @@ -8,8 +8,6 @@ domain="domain.tld" (DOMAIN) path="/" (PATH) is_public=1 (PUBLIC|public=1|private=0) -# password="pass" -# nextclouddomain="domain.tld" port="9980" (PORT) ; Checks pkg_linter=1 @@ -25,18 +23,7 @@ port_already_use=0 change_url=0 ;;; Levels - Level 1=auto - Level 2=auto - Level 3=auto -# Level 4: - Level 4=1 (This app supports the Nextcloud LDAP auth) -# Level 5: Level 5=auto - Level 6=auto - Level 7=auto - Level 8=0 - Level 9=0 - Level 10=0 ;;; Options Email= Notification=none diff --git a/conf/nginx.conf b/conf/nginx.conf index 440cda1..0e7fb48 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,15 +1,17 @@ +location __PATH__/ { + # Force usage of https if ($scheme = http) { rewrite ^ https://$server_name$request_uri? permanent; } -location __PATH__/ { - proxy_pass http://127.0.0.1:__PORT__; + proxy_pass http://127.0.0.1:__PORT__; proxy_http_version 1.1; proxy_buffering off; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $remote_addr; + # needed for websocket proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; diff --git a/manifest.json b/manifest.json index 42da9ea..bed65a3 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "Cockpit package for YunoHost.", "fr": "Cockpit pour YunoHost." }, - "version": "187", + "version": "232~ynh1", "url": "https://cockpit-project.org/", "license": "free", "maintainer": { @@ -14,12 +14,12 @@ "email": "liberodark@gmail.com" }, "requirements": { - "yunohost": ">= 2.7.2" + "yunohost": ">= 4.0.0" }, "multi_instance": false, "services": [ "nginx", - "php5-fpm", + "php7.0-fpm", "mysql" ], "arguments": { @@ -32,7 +32,6 @@ }, "example": "example.com" }, - { "name": "path", "type": "path", @@ -43,15 +42,14 @@ "example": "/cockpit", "default": "/cockpit" }, - { "name": "is_public", "type": "boolean", "ask": { - "en": "Is it a public site ?", + "en": "Is it a public site?", "fr": "Est-ce un site public ?" }, - "default": "true" + "default": true } ] } diff --git a/scripts/_common.sh b/scripts/_common.sh index 0f53f77..3ae2471 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -1,112 +1,22 @@ #!/bin/bash -# ============================================================================= -# YUNOHOST 2.7 FORTHCOMING HELPERS -# ============================================================================= +#================================================= +# COMMON VARIABLES +#================================================= -# 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" - sudo cp ../conf/nginx.conf "$finalnginxconf" +YNH_PHP_VERSION="7.3" - # 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" +# dependencies used by the app +pkg_dependencies="cockpit" - sudo systemctl reload nginx -} +#================================================= +# PERSONAL HELPERS +#================================================= -# 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 -} +#================================================= +# EXPERIMENTAL HELPERS +#================================================= -# 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" - 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" - 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 -} - -# Create a dedicated systemd config -# -# usage: ynh_add_systemd_config -ynh_add_systemd_config () { - finalsystemdconf="/etc/systemd/system/$app.service" - ynh_backup_if_checksum_is_different "$finalsystemdconf" - sudo cp ../conf/systemd.service "$finalsystemdconf" - - # 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 "${final_path:-}"; then - ynh_replace_string "__FINALPATH__" "$final_path" "$finalsystemdconf" - fi - if test -n "${app:-}"; then - ynh_replace_string "__APP__" "$app" "$finalsystemdconf" - fi - ynh_store_file_checksum "$finalsystemdconf" - - sudo chown root: "$finalsystemdconf" - sudo systemctl enable $app - sudo systemctl daemon-reload -} - -# Remove the dedicated systemd config -# -# usage: ynh_remove_systemd_config -ynh_remove_systemd_config () { - finalsystemdconf="/etc/systemd/system/$app.service" - if [ -e "$finalsystemdconf" ]; then - sudo systemctl stop $app - sudo systemctl disable $app - ynh_secure_remove "$finalsystemdconf" - fi -} +#================================================= +# FUTURE OFFICIAL HELPERS +#================================================= diff --git a/scripts/install b/scripts/install index d40a145..f1740bd 100644 --- a/scripts/install +++ b/scripts/install @@ -29,24 +29,13 @@ domain=$YNH_APP_ARG_DOMAIN path_url=$YNH_APP_ARG_PATH is_public=$YNH_APP_ARG_IS_PUBLIC -### If it's a multi-instance app, meaning it can be installed several times independently -### The id of the app as stated in the manifest is available as $YNH_APP_ID -### The instance number is available as $YNH_APP_INSTANCE_NUMBER (equals "1", "2", ...) -### The app instance name is available as $YNH_APP_INSTANCE_NAME -### - the first time the app is installed, YNH_APP_INSTANCE_NAME = ynhexample -### - the second time the app is installed, YNH_APP_INSTANCE_NAME = ynhexample__2 -### - ynhexample__{N} for the subsequent installations, with N=3,4, ... -### The app instance name is probably what interests you most, since this is -### guaranteed to be unique. This is a good unique identifier to define installation path, -### db names, ... app=$YNH_APP_INSTANCE_NAME #================================================= # CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS #================================================= +ynh_script_progression --message="Validating installation parameters..." --weight=1 -### If the app uses nginx as web server (written in HTML/PHP in most cases), the final path should be "/var/www/$app". -### If the app provides an internal web server (or uses another application server such as uwsgi), the final path should be "/opt/yunohost/$app" final_path=/var/www/$app test ! -e "$final_path" || ynh_die "This path already contains a folder" @@ -61,92 +50,38 @@ ynh_webpath_register $app $domain $path_url #================================================= # STORE SETTINGS FROM MANIFEST #================================================= +ynh_script_progression --message="Storing installation settings..." --weight=2 -ynh_app_setting_set $app domain $domain -ynh_app_setting_set $app path $path_url -ynh_app_setting_set $app is_public $is_public - -#============================================== -# INSTALL DEPS -#============================================== - -## Install the backports repo for debian -echo 'deb http://deb.debian.org/debian stretch-backports main' > \ - /etc/apt/sources.list.d/$app.list - -ynh_package_update -ynh_install_app_dependencies cockpit +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 +#================================================= +# STANDARD MODIFICATIONS #================================================= # FIND AND OPEN A PORT #================================================= +ynh_script_progression --message="Configuring firewall..." --weight=2 -### Use these lines if you have to open a port for the application -### `ynh_find_port` will find the first available port starting from the given port. -### If you're not using these lines: -### - Remove the section "CLOSE A PORT" in the remove script - -# Find a free port -port=$(ynh_find_port 9090) -# Open this port -#yunohost firewall allow --no-upnp TCP $port 2>&1 -ynh_app_setting_set $app port $port +# Find an available port +port=$(ynh_find_port --port=9090) +ynh_app_setting_set --app=$app --key=port --value=$port #================================================= -# DOWNLOAD, CHECK AND UNPACK SOURCE +# INSTALL DEPENDENCIES #================================================= +ynh_script_progression --message="Installing dependencies..." --weight=20 -#ynh_app_setting_set $app final_path $final_path -# Download, check integrity, uncompress and patch the source from app.src -#ynh_setup_source "$final_path" +ynh_install_app_dependencies $pkg_dependencies #================================================= # NGINX CONFIGURATION #================================================= +ynh_script_progression --message="Configuring NGINX web server..." --weight=2 -# Create a dedicated nginx config +# Create a dedicated NGINX config ynh_add_nginx_config -#================================================= -# CREATE DEDICATED USER -#================================================= - -# Create a system user -#ynh_system_user_create $app - -#================================================= -# MODIFY A CONFIG FILE -#================================================= -#cp -a ../conf/onlyoffice-documentserver.conf /etc/onlyoffice/documentserver/nginx/onlyoffice-documentserver.conf -#ynh_replace_string "__NEXTCLOUDDOMAIN__" "$nextcloud_domain" "/etc/loolwsd/loolwsd.xml" -#ynh_replace_string "__PASSWORD__" "$password" "/etc/loolwsd/loolwsd.xml" - -#================================================= -# STORE THE CONFIG FILE CHECKSUM -#================================================= - -### `ynh_store_file_checksum` is used to store the checksum of a file. -### That way, during the upgrade script, by using `ynh_backup_if_checksum_is_different`, -### you can make a backup of this file before modifying it again if the admin had modified it. - -# Calculate and store the config file checksum into the app settings -#ynh_store_file_checksum "/etc/onlyoffice/documentserver/nginx/onlyoffice-documentserver.conf" - - -#================================================= -# GENERIC FINALIZATION -#================================================= -# SECURE FILES AND DIRECTORIES -#================================================= - -### 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. - -# Set permissions to app files -#chown -R root: /etc/loolwsd -rm /etc/apt/sources.list.d/$app.list - #================================================= # SETUP SSOWAT #================================================= @@ -158,5 +93,19 @@ if [ $is_public -eq 1 ]; then fi # Reload services +systemctl start cockpit systemctl enable --now cockpit -systemctl reload nginx + +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." --weight=2 + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Installation of HedgeDoc completed" --last + From 671488d935c4951b07e992cd284df693949e1088 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Mon, 16 Nov 2020 19:21:48 +0100 Subject: [PATCH 02/25] Add README --- README.md | 77 +++++++++++++++++++++++++++++++++++++++++---------- manifest.json | 2 +- 2 files changed, 64 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 7ed2a8b..0136fb6 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,71 @@ -# Cockpit app for YunoHost -Cockpit Server - -- [Yunohost project](https://yunohost.org) -- [Cockpit website](https://cockpit-project.org/) - -![](https://avatars0.githubusercontent.com/u/5765104?s=400&v=4) - +# Cockpit for YunoHost +[![Integration level](https://dash.yunohost.org/integration/cockpit.svg)](https://dash.yunohost.org/appci/app/cockpit) ![](https://ci-apps.yunohost.org/ci/badges/cockpit.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/cockpit.maintain.svg) [![Install Cockpit with YunoHost](https://install-app.yunohost.org/install-with-yunohost.png)](https://install-app.yunohost.org/?app=cockpit) -### Installing guide +*[Lire ce readme en français.](./README_fr.md)* - App can be installed by YunoHost **admin web-interface** or by **running following command**: +> *This package allows you to install Cockpit quickly and simply on a YunoHost server. +If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/install) to learn how to install it.* - $ sudo yunohost app install https://github.com/YunoHost-Apps/cockpit_ynh +## Overview +Cockpit makes GNU/Linux discoverable. See your server in a web browser and perform system tasks with a mouse. It’s easy to start containers, administer storage, configure networks, and inspect logs. - -### Upgrade this package: +**Shipped version:** 232 - $ sudo yunohost app upgrade cockpit -u https://github.com/YunoHost-Apps/cockpit_ynh +## Screenshots +![](https://cockpit-project.org/images/site/screenshot-storage.png) + +## Demo + +* [Official demo](Link to a demo site for this app.) + +## Configuration + +How to configure this app: From an admin panel, a plain file with SSH, or any other way. + +## Documentation + + * Official documentation: https://cockpit-project.org/guide/latest/ + * YunoHost documentation: If specific documentation is needed, feel free to contribute. + +## YunoHost specific features + +#### Multi-user support + + * Are LDAP and HTTP auth supported? + * Can the app be used by multiple users? + +#### Supported architectures + +* x86-64 - [![Build Status](https://ci-apps.yunohost.org/ci/logs/cockpit%20%28Apps%29.svg)](https://ci-apps.yunohost.org/ci/apps/cockpit/) +* ARMv8-A - [![Build Status](https://ci-apps-arm.yunohost.org/ci/logs/cockpit%20%28Apps%29.svg)](https://ci-apps-arm.yunohost.org/ci/apps/cockpit/) + +## Limitations + +* Any known limitations. + +## Additional information + +* Other info you would like to add about this app. + +## Links + + * Report a bug: https://github.com/YunoHost-Apps/cockpit_ynh/issues + * App website: https://cockpit-project.org/ + * Upstream app repository: https://github.com/cockpit-project/cockpit + * YunoHost website: https://yunohost.org/ + +--- + +## Developer info + +Please send your pull request to the [testing branch](https://github.com/YunoHost-Apps/cockpit_ynh/tree/testing). + +To try the testing branch, please proceed like that. +``` +sudo yunohost app install https://github.com/YunoHost-Apps/cockpit_ynh/tree/testing --debug +or +sudo yunohost app upgrade cockpit -u https://github.com/YunoHost-Apps/cockpit_ynh/tree/testing --debug +``` diff --git a/manifest.json b/manifest.json index bed65a3..62a1661 100644 --- a/manifest.json +++ b/manifest.json @@ -8,7 +8,7 @@ }, "version": "232~ynh1", "url": "https://cockpit-project.org/", - "license": "free", + "license": "LGPL-2.1-only", "maintainer": { "name": "liberodark", "email": "liberodark@gmail.com" From 35712049d0c0134f41a70407c516f6dae3f6efd2 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Mon, 16 Nov 2020 19:38:35 +0100 Subject: [PATCH 03/25] Fix --- check_process | 3 +- conf/nginx.conf | 9 ++-- scripts/backup | 79 +++++++++++++++++++--------- scripts/install | 50 +++++++++--------- scripts/remove | 77 +++++---------------------- scripts/restore | 137 ++++++++++++++++++++++++++++++++++-------------- scripts/upgrade | 104 +++++++++++++++++++++++------------- 7 files changed, 260 insertions(+), 199 deletions(-) diff --git a/check_process b/check_process index 9bc4859..8964176 100644 --- a/check_process +++ b/check_process @@ -18,8 +18,7 @@ setup_public=1 upgrade=1 backup_restore=1 - multi_instance=1 - incorrect_path=1 + multi_instance=0 port_already_use=0 change_url=0 ;;; Levels diff --git a/conf/nginx.conf b/conf/nginx.conf index 0e7fb48..77f8a9e 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,9 +1,8 @@ -location __PATH__/ { - -# Force usage of https +location ^~ __PATH__/ { + # Force usage of https if ($scheme = http) { rewrite ^ https://$server_name$request_uri? permanent; -} + } proxy_pass http://127.0.0.1:__PORT__; proxy_http_version 1.1; @@ -21,7 +20,7 @@ location __PATH__/ { # Pass ETag header from cockpit to clients. # See: https://github.com/cockpit-project/cockpit/issues/5239 gzip off; -} # Include SSOWAT user panel. include conf.d/yunohost_panel.conf.inc; +} \ No newline at end of file diff --git a/scripts/backup b/scripts/backup index af8ccd9..9bd25df 100644 --- a/scripts/backup +++ b/scripts/backup @@ -1,33 +1,62 @@ #!/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 - -# Source YunoHost helpers +source ../settings/scripts/_common.sh source /usr/share/yunohost/helpers -# Backup sources & data -# Note: the last argument is where to save this path, see the restore script. -ynh_backup "/var/www/${app}" "sources" +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= -### MySQL (remove if not used) ### -# If a MySQL database is used: -# # Dump the database -# dbname=$app -# dbuser=$app -# dbpass=$(ynh_app_setting_get "$app" mysqlpwd) -# mysqldump -u "$dbuser" -p"$dbpass" --no-create-db "$dbname" > ./dump.sql -### MySQL end ### +ynh_clean_setup () { + ynh_clean_check_starting +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors -# Copy NGINX configuration -domain=$(ynh_app_setting_get "$app" domain) -ynh_backup "/etc/nginx/conf.d/${domain}.d/${app}.conf" "nginx.conf" +#================================================= +# LOAD SETTINGS +#================================================= +ynh_print_info --message="Loading installation settings..." -### PHP (remove if not used) ### -# If a dedicated php-fpm process is used: -# # Copy PHP-FPM pool configuration -# ynh_backup "/etc/php5/fpm/pool.d/${app}.conf" "php-fpm.conf" -### PHP end ### +app=$YNH_APP_INSTANCE_NAME + +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +domain=$(ynh_app_setting_get --app=$app --key=domain) + +#================================================= +# DECLARE DATA AND CONF FILES TO BACKUP +#================================================= +ynh_print_info --message="Declaring files to be backed up..." + +#================================================= +# BACKUP THE NGINX CONFIGURATION +#================================================= + +ynh_backup --src_path="/etc/nginx/conf.d/$domain.d/$app.conf" + +#================================================= +# SPECIFIC BACKUP +#================================================= +# BACKUP SYSTEMD +#================================================= + +ynh_backup --src_path="/etc/systemd/system/$app.service" + +#================================================= +# BACKUP THE POSTGRESQL DATABASE +#================================================= +ynh_print_info --message="Backing up the PostgreSQL database..." + +ynh_psql_dump_db --database="$db_name" > db.sql + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_print_info --message="Backup script completed for cockpit. (YunoHost will then actually copy those files to the archive)." diff --git a/scripts/install b/scripts/install index f1740bd..55a585b 100644 --- a/scripts/install +++ b/scripts/install @@ -13,11 +13,6 @@ 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 #================================================= @@ -34,18 +29,18 @@ app=$YNH_APP_INSTANCE_NAME #================================================= # CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS #================================================= -ynh_script_progression --message="Validating installation parameters..." --weight=1 +# ynh_script_progression --message="Validating installation parameters..." --weight=1 -final_path=/var/www/$app -test ! -e "$final_path" || ynh_die "This path already contains a folder" +# final_path=/var/www/$app +# test ! -e "$final_path" || ynh_die "This path already contains a folder" -# Normalize the url path syntax -path_url=$(ynh_normalize_url_path $path_url) +# # Normalize the url path syntax +# path_url=$(ynh_normalize_url_path $path_url) -# Check web path availability -ynh_webpath_available $domain $path_url -# Register (book) web path -ynh_webpath_register $app $domain $path_url +# # Check web path availability +# ynh_webpath_available $domain $path_url +# # Register (book) web path +# ynh_webpath_register $app $domain $path_url #================================================= # STORE SETTINGS FROM MANIFEST @@ -83,18 +78,24 @@ ynh_script_progression --message="Configuring NGINX web server..." --weight=2 ynh_add_nginx_config #================================================= -# SETUP SSOWAT +# START SYSTEMD SERVICE #================================================= - -# If app is public, add url to SSOWat conf as skipped_uris -if [ $is_public -eq 1 ]; then - # unprotected_uris allows SSO credentials to be passed anyway. - ynh_app_setting_set "$app" unprotected_uris "/" -fi +ynh_script_progression --message="Starting a systemd service..." --weight=2 # Reload services -systemctl start cockpit -systemctl enable --now cockpit +ynh_systemd_action --service_name=$app --action="start" +ynh_systemd_action --service_name=$app --action="enable" + +#================================================= +# SETUP SSOWAT +#================================================= +ynh_script_progression --message="Configuring SSOwat..." --weight=1 + +# Make app public if necessary or protect it +if [ $is_public -eq 1 ] +then + ynh_permission_update --permission "main" --add "visitors" +fi #================================================= # RELOAD NGINX @@ -107,5 +108,4 @@ ynh_systemd_action --service_name=nginx --action=reload # END OF SCRIPT #================================================= -ynh_script_progression --message="Installation of HedgeDoc completed" --last - +ynh_script_progression --message="Installation of Cockpit completed" --last diff --git a/scripts/remove b/scripts/remove index 4446429..8090757 100644 --- a/scripts/remove +++ b/scripts/remove @@ -18,27 +18,25 @@ app=$YNH_APP_INSTANCE_NAME domain=$(ynh_app_setting_get $app domain) port=$(ynh_app_setting_get $app port) -db_name=$(ynh_app_setting_get $app db_name) -db_user=$db_name final_path=$(ynh_app_setting_get $app final_path) #================================================= # STANDARD REMOVE #================================================= -# REMOVE SERVICE FROM ADMIN PANEL +# REMOVE SERVICE INTEGRATION IN YUNOHOST #================================================= -# Remove a service from the admin panel, added by `yunohost service add` -if yunohost service status $app >/dev/null 2>&1 +# Remove the service from the list of services known by Yunohost (added from `yunohost service add`) +if ynh_exec_warn_less yunohost service status $app >/dev/null then - ynh_print_info "Removing $app service" + ynh_script_progression --message="Removing $app service..." --weight=1 yunohost service remove $app fi #================================================= # STOP AND REMOVE SERVICE #================================================= -ynh_print_info "Stopping and removing the systemd service" +ynh_script_progression --message="Stopping and removing the systemd service..." --weight=1 # Remove the dedicated systemd config ynh_remove_systemd_config @@ -46,7 +44,7 @@ ynh_remove_systemd_config #================================================= # REMOVE DEPENDENCIES #================================================= -ynh_print_info "Removing dependencies" +ynh_script_progression --message="Removing dependencies..." --weight=1 # Remove metapackage and its dependencies ynh_remove_app_dependencies @@ -54,72 +52,21 @@ ynh_remove_app_dependencies #================================================= # REMOVE APP MAIN DIR #================================================= -ynh_print_info "Removing app main directory" +# ynh_print_info "Removing app main directory" -# Remove the app directory securely -ynh_secure_remove "$final_path" +# # Remove the app directory securely +# ynh_secure_remove "$final_path" #================================================= # REMOVE NGINX CONFIGURATION #================================================= -ynh_print_info "Removing nginx web server configuration" +ynh_script_progression --message="Removing NGINX web server configuration..." --weight=5 -# Remove the dedicated nginx config +# Remove the dedicated NGINX config ynh_remove_nginx_config -#================================================= -# REMOVE PHP-FPM CONFIGURATION -#================================================= -#ynh_print_info "Removing php-fpm configuration" - -# Remove the dedicated php-fpm config -#ynh_remove_fpm_config - -#================================================= -# REMOVE LOGROTATE CONFIGURATION -#================================================= -ynh_print_info "Removing logrotate configuration" - -# Remove the app-specific logrotate config -ynh_remove_logrotate - -#================================================= -# CLOSE A PORT -#================================================= - -if yunohost firewall list | grep -q "\- $port$" -then - ynh_print_info "Closing port $port" - ynh_exec_warn_less yunohost firewall disallow TCP $port -fi - -#================================================= -# SPECIFIC REMOVE -#================================================= -# REMOVE THE CRON FILE -#================================================= - -# Remove a cron file -ynh_secure_remove "/etc/cron.d/$app" - -# Remove a directory securely -ynh_secure_remove "/etc/$app/" - -# Remove the log files -ynh_secure_remove "/var/log/$app/" - -#================================================= -# GENERIC FINALIZATION -#================================================= -# REMOVE DEDICATED USER -#================================================= -ynh_print_info "Removing the dedicated system user" - -# Delete a system user -ynh_system_user_delete $app - #================================================= # END OF SCRIPT #================================================= -ynh_print_info "Removal of $app completed" +ynh_script_progression --message="Removal of HedgeDoc completed" --last diff --git a/scripts/restore b/scripts/restore index 93169e9..0bedcc7 100644 --- a/scripts/restore +++ b/scripts/restore @@ -1,52 +1,109 @@ #!/bin/bash -# Note: each files and directories you've saved using the ynh_backup helper -# will be located in the current directory, regarding the last argument. +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= -# Exit on command errors and treat unset variables as an error -set -eu - -# See comments in install script -app=$YNH_APP_INSTANCE_NAME - -# Source YunoHost helpers +source ../settings/scripts/_common.sh source /usr/share/yunohost/helpers -# Retrieve old app settings -domain=$(ynh_app_setting_get "$app" domain) -path_url=$(ynh_app_setting_get "$app" path_url) +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= -# Check domain/path availability -sudo yunohost app checkurl "${domain}${path_url}" -a "$app" \ - || ynh_die "Path not available: ${domain}${path_url}" +ynh_clean_setup () { + ynh_clean_check_starting +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors -# Restore sources & data -src_path="/var/www/${app}" -sudo cp -a ./sources "$src_path" +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading settings..." --weight=1 -# Restore permissions to app files -# you may need to make some file and/or directory writeable by www-data (nginx user) -sudo chown -R root: "$src_path" +app=$YNH_APP_INSTANCE_NAME -### MySQL (remove if not used) ### -# If a MySQL database is used: -# # Create and restore the database -# dbname=$app -# dbuser=$app -# dbpass=$(ynh_app_setting_get "$app" mysqlpwd) -# ynh_mysql_create_db "$dbname" "$dbuser" "$dbpass" -# ynh_mysql_connect_as "$dbuser" "$dbpass" "$dbname" < ./dump.sql -### MySQL end ### +domain=$(ynh_app_setting_get --app=$app --key=domain) +path_url=$(ynh_app_setting_get --app=$app --key=path) -# Restore NGINX configuration -sudo cp -a ./nginx.conf "/etc/nginx/conf.d/${domain}.d/${app}.conf" -### PHP (remove if not used) ### -# If a dedicated php-fpm process is used: -# # Copy PHP-FPM pool configuration and reload the service -# sudo cp -a ./php-fpm.conf "/etc/php5/fpm/pool.d/${app}.conf" -# sudo service php5-fpm reload -### PHP end ### +#================================================= +# CHECK IF THE APP CAN BE RESTORED +#================================================= +ynh_script_progression --message="Validating restoration parameters..." --weight=2 -# Restart webserver -sudo service nginx reload +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 " + +#================================================= +# STANDARD RESTORATION STEPS +#================================================= +# RESTORE THE NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Restoring the NGINX configuration..." + +ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" + +#================================================= +# SPECIFIC RESTORATION +#================================================= +# REINSTALL DEPENDENCIES +#================================================= +ynh_script_progression --message="Reinstalling dependencies..." --weight=7 + +# Define and install dependencies +ynh_install_app_dependencies $pkg_dependencies + +#================================================= +# RESTORE SYSTEMD +#================================================= +ynh_script_progression --message="Restoring the systemd configuration..." --weight=5 + +ynh_restore_file --origin_path="/etc/systemd/system/$app.service" +systemctl enable $app.service + +#================================================= +# NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Configuring NGINX web server..." --weight=2 + +# Create a dedicated NGINX config +ynh_add_nginx_config + +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." --weight=2 + +# Reload services +ynh_systemd_action --service_name=$app --action="start" +ynh_systemd_action --service_name=$app --action="enable" + +#================================================= +# SETUP SSOWAT +#================================================= +ynh_script_progression --message="Configuring SSOwat..." --weight=1 + +# Make app public if necessary or protect it +if [ $is_public -eq 1 ] +then + ynh_permission_update --permission "main" --add "visitors" +fi + +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." --weight=2 + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Installation of Cockpit completed" --last diff --git a/scripts/upgrade b/scripts/upgrade index 1500467..8511cd0 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -1,60 +1,90 @@ #!/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 -final_path=/opt/yunohost/$app - -# Source YunoHost helpers +source _common.sh source /usr/share/yunohost/helpers -# Stop cockpit service -systemctl stop cockpit +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." --weight=2 -#============================================== -# INSTALL DEPS -#============================================== +app=$YNH_APP_INSTANCE_NAME -## Install the backports repo for debian -echo 'deb http://deb.debian.org/debian stretch-backports main' > \ - /etc/apt/sources.list.d/$app.list +domain=$(ynh_app_setting_get --app=$app --key=domain) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +port=$(ynh_app_setting_get --app=$app --key=port) -ynh_package_update +#final_path=/opt/yunohost/$app -#============================================== -# INSTALL COCKPIT -#============================================== +#================================================= +# CHECK VERSION +#================================================= +ynh_script_progression --message="Checking version..." -ynh_package_install cockpit +upgrade_type=$(ynh_check_app_version_changed) + +#================================================= +# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP +#================================================= +ynh_script_progression --message="Backing up HedgeDoc before upgrading (may take a while)..." --weight=120 + +# 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..." --weight=1 + +ynh_systemd_action --service_name=$app --action="stop" --log_path="systemd" + +#================================================= +# INSTALL DEPENDENCIES +#================================================= +ynh_script_progression --message="Installing dependencies..." --weight=20 + +ynh_install_app_dependencies $pkg_dependencies #================================================= # NGINX CONFIGURATION #================================================= +ynh_script_progression --message="Configuring NGINX web server..." --weight=2 -# Create a dedicated nginx config -#ynh_add_nginx_config - +# Create a dedicated NGINX config +ynh_add_nginx_config #================================================= -# UPGRADE CONFIG +# START SYSTEMD SERVICE #================================================= -#cp -a ../conf/loolwsd.xml /etc/loolwsd -#ynh_replace_string "__NEXTCLOUDDOMAIN__" "$nextcloud_domain" "/etc/loolwsd/loolwsd.xml" -#ynh_replace_string "__PASSWORD__" "$password" "/etc/loolwsd/loolwsd.xml" -#systemctl restart loolwsd +ynh_script_progression --message="Starting a systemd service..." --weight=2 +# Reload services +ynh_systemd_action --service_name=$app --action="start" +ynh_systemd_action --service_name=$app --action="enable" +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." --weight=2 -# If app is public, add url to SSOWat conf as skipped_uris -#if [[ $is_public -eq 1 ]]; then - # See install script -# ynh_app_setting_set "$app" unprotected_uris "/" -#fi +ynh_systemd_action --service_name=nginx --action=reload -rm /etc/apt/sources.list.d/$app.list - -# Start cockpit service -systemctl start cockpit +#================================================= +# END OF SCRIPT +#================================================= +ynh_script_progression --message="Installation of Cockpit completed" --last \ No newline at end of file From a917676a7469404a8e71b00175a47e5ed0ed7afe Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Mon, 16 Nov 2020 19:51:33 +0100 Subject: [PATCH 04/25] Fix --- manifest.json | 5 ++--- scripts/_common.sh | 2 -- scripts/upgrade | 6 ++---- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/manifest.json b/manifest.json index 62a1661..82b8ad0 100644 --- a/manifest.json +++ b/manifest.json @@ -3,8 +3,8 @@ "id": "cockpit", "packaging_format": 1, "description": { - "en": "Cockpit package for YunoHost.", - "fr": "Cockpit pour YunoHost." + "en": "Sysadmin login session in a web browser.", + "fr": "Session de connexion sysadmin dans un navigateur Web." }, "version": "232~ynh1", "url": "https://cockpit-project.org/", @@ -19,7 +19,6 @@ "multi_instance": false, "services": [ "nginx", - "php7.0-fpm", "mysql" ], "arguments": { diff --git a/scripts/_common.sh b/scripts/_common.sh index 3ae2471..e480917 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -4,8 +4,6 @@ # COMMON VARIABLES #================================================= -YNH_PHP_VERSION="7.3" - # dependencies used by the app pkg_dependencies="cockpit" diff --git a/scripts/upgrade b/scripts/upgrade index 8511cd0..6a3d4a1 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -20,8 +20,6 @@ domain=$(ynh_app_setting_get --app=$app --key=domain) final_path=$(ynh_app_setting_get --app=$app --key=final_path) port=$(ynh_app_setting_get --app=$app --key=port) -#final_path=/opt/yunohost/$app - #================================================= # CHECK VERSION #================================================= @@ -32,7 +30,7 @@ upgrade_type=$(ynh_check_app_version_changed) #================================================= # BACKUP BEFORE UPGRADE THEN ACTIVE TRAP #================================================= -ynh_script_progression --message="Backing up HedgeDoc before upgrading (may take a while)..." --weight=120 +ynh_script_progression --message="Backing up HedgeDoc before upgrading (may take a while)..." --weight=12 # Backup the current version of the app ynh_backup_before_upgrade @@ -87,4 +85,4 @@ ynh_systemd_action --service_name=nginx --action=reload # END OF SCRIPT #================================================= -ynh_script_progression --message="Installation of Cockpit completed" --last \ No newline at end of file +ynh_script_progression --message="Installation of Cockpit completed" --last From 1712e31d3401ad5187afbdd418daeae02dca5536 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Mon, 16 Nov 2020 20:05:17 +0100 Subject: [PATCH 05/25] Update install --- scripts/install | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/install b/scripts/install index 55a585b..009a3ee 100644 --- a/scripts/install +++ b/scripts/install @@ -83,8 +83,8 @@ ynh_add_nginx_config ynh_script_progression --message="Starting a systemd service..." --weight=2 # Reload services -ynh_systemd_action --service_name=$app --action="start" -ynh_systemd_action --service_name=$app --action="enable" +systemctl start $app +systemctl enable --now $app #================================================= # SETUP SSOWAT From 6f5f79d96038553fce06f8288d524bf02c99d5b9 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Wed, 7 Jul 2021 19:03:00 +0200 Subject: [PATCH 06/25] fix --- check_process | 16 ++++------------ conf/nginx.conf | 1 + manifest.json | 14 +------------- scripts/install | 1 - 4 files changed, 6 insertions(+), 26 deletions(-) diff --git a/check_process b/check_process index 8964176..057ec49 100644 --- a/check_process +++ b/check_process @@ -1,14 +1,9 @@ -# See here for more informations -# https://github.com/YunoHost/package_check#syntax-check_process-file - -# Move this file from check_process.default to check_process when you have filled it. - ;; Test complet ; Manifest - domain="domain.tld" (DOMAIN) - path="/" (PATH) - is_public=1 (PUBLIC|public=1|private=0) - port="9980" (PORT) + domain="domain.tld" + path="/" + is_public=1 + port="9090" ; Checks pkg_linter=1 setup_sub_dir=0 @@ -19,10 +14,7 @@ upgrade=1 backup_restore=1 multi_instance=0 - port_already_use=0 change_url=0 -;;; Levels - Level 5=auto ;;; Options Email= Notification=none diff --git a/conf/nginx.conf b/conf/nginx.conf index 77f8a9e..96dea0f 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,4 +1,5 @@ location ^~ __PATH__/ { + # Force usage of https if ($scheme = http) { rewrite ^ https://$server_name$request_uri? permanent; diff --git a/manifest.json b/manifest.json index 82b8ad0..f345bdc 100644 --- a/manifest.json +++ b/manifest.json @@ -14,7 +14,7 @@ "email": "liberodark@gmail.com" }, "requirements": { - "yunohost": ">= 4.0.0" + "yunohost": ">= 4.2.4" }, "multi_instance": false, "services": [ @@ -25,29 +25,17 @@ "install": [{ "name": "domain", "type": "domain", - "ask": { - "en": "Choose a domain name for Cockpit", - "fr": "Choisissez un nom de domaine pour Cockpit" - }, "example": "example.com" }, { "name": "path", "type": "path", - "ask": { - "en": "Choose a path for Cockpit /cockpit is accepted", - "fr": "Choisissez un chemin pour Cockpit /cockpit est accepté" - }, "example": "/cockpit", "default": "/cockpit" }, { "name": "is_public", "type": "boolean", - "ask": { - "en": "Is it a public site?", - "fr": "Est-ce un site public ?" - }, "default": true } ] diff --git a/scripts/install b/scripts/install index 009a3ee..6a96439 100644 --- a/scripts/install +++ b/scripts/install @@ -49,7 +49,6 @@ ynh_script_progression --message="Storing installation settings..." --weight=2 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 #================================================= # STANDARD MODIFICATIONS From 804e915759d2cdffcfc2e2fabfab2971102da24e Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Wed, 7 Jul 2021 19:08:59 +0200 Subject: [PATCH 07/25] Fix --- doc/.DS_Store | Bin 0 -> 6148 bytes doc/DISCLAIMER.md | 0 doc/screenshots/screenshot-storage.png | Bin 0 -> 32272 bytes scripts/install | 2 +- scripts/remove | 2 +- scripts/restore | 3 +-- scripts/upgrade | 2 +- 7 files changed, 4 insertions(+), 5 deletions(-) create mode 100644 doc/.DS_Store create mode 100644 doc/DISCLAIMER.md create mode 100644 doc/screenshots/screenshot-storage.png diff --git a/doc/.DS_Store b/doc/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c90376b56b73b627c519d1a34c5d8c9abb7004dc GIT binary patch literal 6148 zcmeHKyG{c^3>-s>NNG}1?l15Mt0;UyegFv&DbPhqfch%Fi%(bFB<-Yt6!=#P*lfL7ulP#UTPH8)y|&RG>0a|qcjG!J4AG8> j(T=(Cc6=8_S=W5c^IkY62A%n!6ZJFTy2zx!wH5dQ#>Eyj literal 0 HcmV?d00001 diff --git a/doc/DISCLAIMER.md b/doc/DISCLAIMER.md new file mode 100644 index 0000000..e69de29 diff --git a/doc/screenshots/screenshot-storage.png b/doc/screenshots/screenshot-storage.png new file mode 100644 index 0000000000000000000000000000000000000000..8f78c9410c9ceeb069d817abcc67bc88f9f0f07c GIT binary patch literal 32272 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 literal 0 HcmV?d00001 diff --git a/scripts/install b/scripts/install index 6a96439..8630eec 100644 --- a/scripts/install +++ b/scripts/install @@ -107,4 +107,4 @@ ynh_systemd_action --service_name=nginx --action=reload # END OF SCRIPT #================================================= -ynh_script_progression --message="Installation of Cockpit completed" --last +ynh_script_progression --message="Installation of $app completed" --last diff --git a/scripts/remove b/scripts/remove index 8090757..a327b7a 100644 --- a/scripts/remove +++ b/scripts/remove @@ -69,4 +69,4 @@ ynh_remove_nginx_config # END OF SCRIPT #================================================= -ynh_script_progression --message="Removal of HedgeDoc completed" --last +ynh_script_progression --message="Removal of $app completed" --last diff --git a/scripts/restore b/scripts/restore index 0bedcc7..794a868 100644 --- a/scripts/restore +++ b/scripts/restore @@ -29,7 +29,6 @@ app=$YNH_APP_INSTANCE_NAME domain=$(ynh_app_setting_get --app=$app --key=domain) path_url=$(ynh_app_setting_get --app=$app --key=path) - #================================================= # CHECK IF THE APP CAN BE RESTORED #================================================= @@ -106,4 +105,4 @@ ynh_systemd_action --service_name=nginx --action=reload # END OF SCRIPT #================================================= -ynh_script_progression --message="Installation of Cockpit completed" --last +ynh_script_progression --message="Installation of $app completed" --last diff --git a/scripts/upgrade b/scripts/upgrade index 6a3d4a1..84921ee 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -85,4 +85,4 @@ ynh_systemd_action --service_name=nginx --action=reload # END OF SCRIPT #================================================= -ynh_script_progression --message="Installation of Cockpit completed" --last +ynh_script_progression --message="Installation of $app completed" --last From e835686e87d585989b2ea1e40cffaa19d394c9d2 Mon Sep 17 00:00:00 2001 From: Yunohost-Bot <> Date: Wed, 7 Jul 2021 17:09:05 +0000 Subject: [PATCH 08/25] Auto-update README --- README.md | 63 +++++++++++++++------------------------------------- README_fr.md | 40 +++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 45 deletions(-) create mode 100644 README_fr.md diff --git a/README.md b/README.md index 0136fb6..564ab86 100644 --- a/README.md +++ b/README.md @@ -1,63 +1,34 @@ + + # Cockpit for YunoHost [![Integration level](https://dash.yunohost.org/integration/cockpit.svg)](https://dash.yunohost.org/appci/app/cockpit) ![](https://ci-apps.yunohost.org/ci/badges/cockpit.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/cockpit.maintain.svg) -[![Install Cockpit with YunoHost](https://install-app.yunohost.org/install-with-yunohost.png)](https://install-app.yunohost.org/?app=cockpit) +[![Install Cockpit with YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=cockpit) *[Lire ce readme en français.](./README_fr.md)* -> *This package allows you to install Cockpit quickly and simply on a YunoHost server. +> *This package allows you to install Cockpit quickly and simply on a YunoHost server. If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/install) to learn how to install it.* ## Overview -Cockpit makes GNU/Linux discoverable. See your server in a web browser and perform system tasks with a mouse. It’s easy to start containers, administer storage, configure networks, and inspect logs. -**Shipped version:** 232 +Sysadmin login session in a web browser. + +**Shipped version:** 232~ynh1 + + ## Screenshots -![](https://cockpit-project.org/images/site/screenshot-storage.png) +![](./doc/screenshots/screenshot-storage.png) -## Demo +## Documentation and resources -* [Official demo](Link to a demo site for this app.) - -## Configuration - -How to configure this app: From an admin panel, a plain file with SSH, or any other way. - -## Documentation - - * Official documentation: https://cockpit-project.org/guide/latest/ - * YunoHost documentation: If specific documentation is needed, feel free to contribute. - -## YunoHost specific features - -#### Multi-user support - - * Are LDAP and HTTP auth supported? - * Can the app be used by multiple users? - -#### Supported architectures - -* x86-64 - [![Build Status](https://ci-apps.yunohost.org/ci/logs/cockpit%20%28Apps%29.svg)](https://ci-apps.yunohost.org/ci/apps/cockpit/) -* ARMv8-A - [![Build Status](https://ci-apps-arm.yunohost.org/ci/logs/cockpit%20%28Apps%29.svg)](https://ci-apps-arm.yunohost.org/ci/apps/cockpit/) - -## Limitations - -* Any known limitations. - -## Additional information - -* Other info you would like to add about this app. - -## Links - - * Report a bug: https://github.com/YunoHost-Apps/cockpit_ynh/issues - * App website: https://cockpit-project.org/ - * Upstream app repository: https://github.com/cockpit-project/cockpit - * YunoHost website: https://yunohost.org/ - ---- +* YunoHost documentation for this app: https://yunohost.org/app_cockpit +* Report a bug: https://github.com/YunoHost-Apps/cockpit_ynh/issues ## Developer info @@ -69,3 +40,5 @@ sudo yunohost app install https://github.com/YunoHost-Apps/cockpit_ynh/tree/test or sudo yunohost app upgrade cockpit -u https://github.com/YunoHost-Apps/cockpit_ynh/tree/testing --debug ``` + +**More info regarding app packaging:** https://yunohost.org/packaging_apps \ No newline at end of file diff --git a/README_fr.md b/README_fr.md new file mode 100644 index 0000000..f653e05 --- /dev/null +++ b/README_fr.md @@ -0,0 +1,40 @@ +# Cockpit pour YunoHost + +[![Niveau d'intégration](https://dash.yunohost.org/integration/cockpit.svg)](https://dash.yunohost.org/appci/app/cockpit) ![](https://ci-apps.yunohost.org/ci/badges/cockpit.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/cockpit.maintain.svg) +[![Installer Cockpit avec YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=cockpit) + +*[Read this readme in english.](./README.md)* +*[Lire ce readme en français.](./README_fr.md)* + +> *Ce package vous permet d'installer Cockpit rapidement et simplement sur un serveur YunoHost. +Si vous n'avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour savoir comment l'installer et en profiter.* + +## Vue d'ensemble + +Session de connexion sysadmin dans un navigateur Web. + +**Version incluse :** 232~ynh1 + + + +## Captures d'écran + +![](./doc/screenshots/screenshot-storage.png) + +## Documentations et ressources + +* Documentation YunoHost pour cette app : https://yunohost.org/app_cockpit +* Signaler un bug : https://github.com/YunoHost-Apps/cockpit_ynh/issues + +## Informations pour les développeurs + +Merci de faire vos pull request sur la [branche testing](https://github.com/YunoHost-Apps/cockpit_ynh/tree/testing). + +Pour essayer la branche testing, procédez comme suit. +``` +sudo yunohost app install https://github.com/YunoHost-Apps/cockpit_ynh/tree/testing --debug +ou +sudo yunohost app upgrade cockpit -u https://github.com/YunoHost-Apps/cockpit_ynh/tree/testing --debug +``` + +**Plus d'infos sur le packaging d'applications :** https://yunohost.org/packaging_apps \ No newline at end of file From e15401d0518d341fb0294096e7050d71e791dd04 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Wed, 7 Jul 2021 19:27:38 +0200 Subject: [PATCH 09/25] Fix --- conf/nginx.conf | 8 +++----- scripts/backup | 7 ------- scripts/install | 6 +++--- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/conf/nginx.conf b/conf/nginx.conf index 96dea0f..96f0c5f 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,5 +1,6 @@ +#sub_path_only rewrite ^__PATH__$ __PATH__/ permanent; location ^~ __PATH__/ { - + # Force usage of https if ($scheme = http) { rewrite ^ https://$server_name$request_uri? permanent; @@ -18,10 +19,7 @@ location ^~ __PATH__/ { # change scheme of "Origin" to http proxy_set_header Origin http://$host; - # Pass ETag header from cockpit to clients. - # See: https://github.com/cockpit-project/cockpit/issues/5239 - gzip off; # Include SSOWAT user panel. include conf.d/yunohost_panel.conf.inc; -} \ No newline at end of file +} diff --git a/scripts/backup b/scripts/backup index 9bd25df..b8c5fad 100644 --- a/scripts/backup +++ b/scripts/backup @@ -48,13 +48,6 @@ ynh_backup --src_path="/etc/nginx/conf.d/$domain.d/$app.conf" ynh_backup --src_path="/etc/systemd/system/$app.service" -#================================================= -# BACKUP THE POSTGRESQL DATABASE -#================================================= -ynh_print_info --message="Backing up the PostgreSQL database..." - -ynh_psql_dump_db --database="$db_name" > db.sql - #================================================= # END OF SCRIPT #================================================= diff --git a/scripts/install b/scripts/install index 8630eec..38a1043 100644 --- a/scripts/install +++ b/scripts/install @@ -47,8 +47,8 @@ app=$YNH_APP_INSTANCE_NAME #================================================= ynh_script_progression --message="Storing installation settings..." --weight=2 -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=domain --value=$domain +ynh_app_setting_set --app=$app --key=path --value=$path_url #================================================= # STANDARD MODIFICATIONS @@ -83,7 +83,7 @@ ynh_script_progression --message="Starting a systemd service..." --weight=2 # Reload services systemctl start $app -systemctl enable --now $app +systemctl enable $app --quiet #================================================= # SETUP SSOWAT From 1b5539229370577be2629da9fd6b456577d51752 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Thu, 25 Nov 2021 18:45:05 +0100 Subject: [PATCH 10/25] Fix --- conf/nginx.conf | 5 ----- doc/DESCRIPTION.md | 1 + manifest.json | 21 +++++++++++++-------- scripts/restore | 5 +---- 4 files changed, 15 insertions(+), 17 deletions(-) create mode 100644 doc/DESCRIPTION.md diff --git a/conf/nginx.conf b/conf/nginx.conf index 96f0c5f..9e0344f 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,11 +1,6 @@ #sub_path_only rewrite ^__PATH__$ __PATH__/ permanent; location ^~ __PATH__/ { - # Force usage of https - if ($scheme = http) { - rewrite ^ https://$server_name$request_uri? permanent; - } - proxy_pass http://127.0.0.1:__PORT__; proxy_http_version 1.1; proxy_buffering off; diff --git a/doc/DESCRIPTION.md b/doc/DESCRIPTION.md new file mode 100644 index 0000000..d33d446 --- /dev/null +++ b/doc/DESCRIPTION.md @@ -0,0 +1 @@ +Cockpit is a web-based graphical interface for servers, intended for everyone. \ No newline at end of file diff --git a/manifest.json b/manifest.json index f345bdc..e9dbce2 100644 --- a/manifest.json +++ b/manifest.json @@ -3,29 +3,34 @@ "id": "cockpit", "packaging_format": 1, "description": { - "en": "Sysadmin login session in a web browser.", - "fr": "Session de connexion sysadmin dans un navigateur Web." + "en": "Sysadmin login session in a web browser", + "fr": "Session de connexion sysadmin dans un navigateur Web" }, - "version": "232~ynh1", + "version": "257~ynh1", "url": "https://cockpit-project.org/", + "upstream": { + "license": "LGPL-2.1-only", + "website": "https://cockpit-project.org/", + "demo": "https://demo.example.com", + "admindoc": "https://cockpit-project.org/documentation.html", + "code": "https://some.forge.com/example/example" + }, "license": "LGPL-2.1-only", "maintainer": { "name": "liberodark", "email": "liberodark@gmail.com" }, "requirements": { - "yunohost": ">= 4.2.4" + "yunohost": ">= 4.3.0" }, "multi_instance": false, "services": [ - "nginx", - "mysql" + "nginx" ], "arguments": { "install": [{ "name": "domain", - "type": "domain", - "example": "example.com" + "type": "domain" }, { "name": "path", diff --git a/scripts/restore b/scripts/restore index 794a868..050f3f8 100644 --- a/scripts/restore +++ b/scripts/restore @@ -34,10 +34,7 @@ path_url=$(ynh_app_setting_get --app=$app --key=path) #================================================= ynh_script_progression --message="Validating restoration parameters..." --weight=2 -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 " +test ! -d $final_path || ynh_die --message="There is already a directory: $final_path " #================================================= # STANDARD RESTORATION STEPS From c4d495602ade67e7869a9b1afdd9972f6b783c94 Mon Sep 17 00:00:00 2001 From: Yunohost-Bot <> Date: Thu, 25 Nov 2021 17:45:11 +0000 Subject: [PATCH 11/25] Auto-update README --- README.md | 9 ++++++--- README_fr.md | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 564ab86..5c34233 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,11 @@ If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/in ## Overview -Sysadmin login session in a web browser. - -**Shipped version:** 232~ynh1 +Cockpit is a web-based graphical interface for servers, intended for everyone. +**Shipped version:** 257~ynh1 +**Demo:** https://demo.example.com ## Screenshots @@ -27,6 +27,9 @@ Sysadmin login session in a web browser. ## Documentation and resources +* Official app website: https://cockpit-project.org/ +* Official admin documentation: https://cockpit-project.org/documentation.html +* Upstream app code repository: https://some.forge.com/example/example * YunoHost documentation for this app: https://yunohost.org/app_cockpit * Report a bug: https://github.com/YunoHost-Apps/cockpit_ynh/issues diff --git a/README_fr.md b/README_fr.md index f653e05..1d91fce 100644 --- a/README_fr.md +++ b/README_fr.md @@ -11,11 +11,11 @@ Si vous n'avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour ## Vue d'ensemble -Session de connexion sysadmin dans un navigateur Web. - -**Version incluse :** 232~ynh1 +Cockpit is a web-based graphical interface for servers, intended for everyone. +**Version incluse :** 257~ynh1 +**Démo :** https://demo.example.com ## Captures d'écran @@ -23,6 +23,9 @@ Session de connexion sysadmin dans un navigateur Web. ## Documentations et ressources +* Site officiel de l'app : https://cockpit-project.org/ +* Documentation officielle de l'admin : https://cockpit-project.org/documentation.html +* Dépôt de code officiel de l'app : https://some.forge.com/example/example * Documentation YunoHost pour cette app : https://yunohost.org/app_cockpit * Signaler un bug : https://github.com/YunoHost-Apps/cockpit_ynh/issues From 1edd5bbe593f60e08ea263ab73dda06f6eef6807 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Mon, 6 Dec 2021 22:54:30 +0100 Subject: [PATCH 12/25] Fix --- conf/cockpit.conf | 8 ++++++++ manifest.json | 12 +++++++----- scripts/install | 10 ++++++++-- 3 files changed, 23 insertions(+), 7 deletions(-) create mode 100644 conf/cockpit.conf diff --git a/conf/cockpit.conf b/conf/cockpit.conf new file mode 100644 index 0000000..4adb59a --- /dev/null +++ b/conf/cockpit.conf @@ -0,0 +1,8 @@ +[WebService] +Origins = https://__DOMAIN__ +https://127.0.0.1:9090 + +[WebService] +ProtocolHeader = X-Forwarded-Proto + +UrlRoot = __PATH__/ \ No newline at end of file diff --git a/manifest.json b/manifest.json index e9dbce2..ab8b47e 100644 --- a/manifest.json +++ b/manifest.json @@ -11,9 +11,7 @@ "upstream": { "license": "LGPL-2.1-only", "website": "https://cockpit-project.org/", - "demo": "https://demo.example.com", - "admindoc": "https://cockpit-project.org/documentation.html", - "code": "https://some.forge.com/example/example" + "admindoc": "https://cockpit-project.org/documentation.html" }, "license": "LGPL-2.1-only", "maintainer": { @@ -35,8 +33,12 @@ { "name": "path", "type": "path", - "example": "/cockpit", - "default": "/cockpit" + "help": { + "en": "/cockpit/ and /cockpit+ are reserved and should not be used.", + "fr": "/cockpit/ et /cockpit+ sont réservés et ne doivent pas être utilisés." + }, + "example": "/monitor", + "default": "/monitor" }, { "name": "is_public", diff --git a/scripts/install b/scripts/install index 38a1043..9e75e99 100644 --- a/scripts/install +++ b/scripts/install @@ -68,6 +68,13 @@ ynh_script_progression --message="Installing dependencies..." --weight=20 ynh_install_app_dependencies $pkg_dependencies +#================================================= +# ADD A CONFIGURATION +#================================================= +ynh_script_progression --message="Adding a configuration file..." --weight=1 + +ynh_add_config --template="../conf/cockpite.conf" --destination="/etc/cockpit/cockpit.conf" + #================================================= # NGINX CONFIGURATION #================================================= @@ -82,8 +89,7 @@ ynh_add_nginx_config ynh_script_progression --message="Starting a systemd service..." --weight=2 # Reload services -systemctl start $app -systemctl enable $app --quiet +systemctl enable cockpit.socket --quiet #================================================= # SETUP SSOWAT From 3e333d1c4ad2c106cbfdae2570d5d5c71391d8b7 Mon Sep 17 00:00:00 2001 From: Yunohost-Bot <> Date: Mon, 6 Dec 2021 21:54:37 +0000 Subject: [PATCH 13/25] Auto-update README --- README.md | 3 +-- README_fr.md | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5c34233..5d95937 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Cockpit is a web-based graphical interface for servers, intended for everyone. **Shipped version:** 257~ynh1 -**Demo:** https://demo.example.com + ## Screenshots @@ -29,7 +29,6 @@ Cockpit is a web-based graphical interface for servers, intended for everyone. * Official app website: https://cockpit-project.org/ * Official admin documentation: https://cockpit-project.org/documentation.html -* Upstream app code repository: https://some.forge.com/example/example * YunoHost documentation for this app: https://yunohost.org/app_cockpit * Report a bug: https://github.com/YunoHost-Apps/cockpit_ynh/issues diff --git a/README_fr.md b/README_fr.md index 1d91fce..b55e13d 100644 --- a/README_fr.md +++ b/README_fr.md @@ -15,7 +15,7 @@ Cockpit is a web-based graphical interface for servers, intended for everyone. **Version incluse :** 257~ynh1 -**Démo :** https://demo.example.com + ## Captures d'écran @@ -25,7 +25,6 @@ Cockpit is a web-based graphical interface for servers, intended for everyone. * Site officiel de l'app : https://cockpit-project.org/ * Documentation officielle de l'admin : https://cockpit-project.org/documentation.html -* Dépôt de code officiel de l'app : https://some.forge.com/example/example * Documentation YunoHost pour cette app : https://yunohost.org/app_cockpit * Signaler un bug : https://github.com/YunoHost-Apps/cockpit_ynh/issues From 86a3973511709634ac8b67162c72ac537d1ed72a Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Mon, 6 Dec 2021 22:57:44 +0100 Subject: [PATCH 14/25] Update install --- scripts/install | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/install b/scripts/install index 9e75e99..7a7516c 100644 --- a/scripts/install +++ b/scripts/install @@ -66,14 +66,14 @@ ynh_app_setting_set --app=$app --key=port --value=$port #================================================= ynh_script_progression --message="Installing dependencies..." --weight=20 -ynh_install_app_dependencies $pkg_dependencies +ynh_exec_warn_less ynh_install_app_dependencies $pkg_dependencies #================================================= # ADD A CONFIGURATION #================================================= ynh_script_progression --message="Adding a configuration file..." --weight=1 -ynh_add_config --template="../conf/cockpite.conf" --destination="/etc/cockpit/cockpit.conf" +ynh_add_config --template="../conf/cockpit.conf" --destination="/etc/cockpit/cockpit.conf" #================================================= # NGINX CONFIGURATION From 43b1e23c12a2ff3fe6ed33d31d54084eace5a01a Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Mon, 6 Dec 2021 23:01:56 +0100 Subject: [PATCH 15/25] Update install --- scripts/install | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/scripts/install b/scripts/install index 7a7516c..9ed57aa 100644 --- a/scripts/install +++ b/scripts/install @@ -89,18 +89,25 @@ ynh_add_nginx_config ynh_script_progression --message="Starting a systemd service..." --weight=2 # Reload services -systemctl enable cockpit.socket --quiet +#systemctl enable cockpit.socket --quiet +ynh_systemd_action --service_name=cockpit.socket --action=start + +#================================================= +# ADVERTISE SERVICE IN ADMIN PANEL +#================================================= + +yunohost service add cockpit.socket --description="Monitor" #--log="/var/log/syslog" #================================================= # SETUP SSOWAT #================================================= -ynh_script_progression --message="Configuring SSOwat..." --weight=1 +# ynh_script_progression --message="Configuring SSOwat..." --weight=1 -# Make app public if necessary or protect it -if [ $is_public -eq 1 ] -then - ynh_permission_update --permission "main" --add "visitors" -fi +# # Make app public if necessary or protect it +# if [ $is_public -eq 1 ] +# then +# ynh_permission_update --permission "main" --add "visitors" +# fi #================================================= # RELOAD NGINX From dff622dcdac6adca3a5a17329a4730c7dff9d24a Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Mon, 6 Dec 2021 23:06:28 +0100 Subject: [PATCH 16/25] Update install --- scripts/install | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/install b/scripts/install index 9ed57aa..9101304 100644 --- a/scripts/install +++ b/scripts/install @@ -90,7 +90,7 @@ ynh_script_progression --message="Starting a systemd service..." --weight=2 # Reload services #systemctl enable cockpit.socket --quiet -ynh_systemd_action --service_name=cockpit.socket --action=start +#ynh_systemd_action --service_name=cockpit.socket --action=start #================================================= # ADVERTISE SERVICE IN ADMIN PANEL @@ -98,6 +98,8 @@ ynh_systemd_action --service_name=cockpit.socket --action=start yunohost service add cockpit.socket --description="Monitor" #--log="/var/log/syslog" +ynh_systemd_action --service_name=cockpit.socket --action="start" --log_path="/var/log/$app/$app.log" + #================================================= # SETUP SSOWAT #================================================= From 9ac97734ed74715e54085b5b7e8e25b9e26230eb Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Mon, 6 Dec 2021 23:12:58 +0100 Subject: [PATCH 17/25] Fix --- conf/nginx.conf | 2 +- manifest.json | 5 ----- scripts/install | 28 +++++++--------------------- scripts/remove | 10 +--------- 4 files changed, 9 insertions(+), 36 deletions(-) diff --git a/conf/nginx.conf b/conf/nginx.conf index 9e0344f..d386d46 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,7 +1,7 @@ #sub_path_only rewrite ^__PATH__$ __PATH__/ permanent; location ^~ __PATH__/ { - proxy_pass http://127.0.0.1:__PORT__; + proxy_pass http://127.0.0.1:__PORT__/; proxy_http_version 1.1; proxy_buffering off; proxy_set_header X-Real-IP $remote_addr; diff --git a/manifest.json b/manifest.json index ab8b47e..5f88acf 100644 --- a/manifest.json +++ b/manifest.json @@ -39,11 +39,6 @@ }, "example": "/monitor", "default": "/monitor" - }, - { - "name": "is_public", - "type": "boolean", - "default": true } ] } diff --git a/scripts/install b/scripts/install index 9101304..87b5f56 100644 --- a/scripts/install +++ b/scripts/install @@ -83,34 +83,20 @@ ynh_script_progression --message="Configuring NGINX web server..." --weight=2 # Create a dedicated NGINX config ynh_add_nginx_config +#================================================= +# INTEGRATE SERVICE IN YUNOHOST +#================================================= +ynh_script_progression --message="Integrating service in YunoHost..." --weight=1 + +yunohost service add cockpit.socket --description="Monitor" --log="/var/log/$app/$app.log" + #================================================= # START SYSTEMD SERVICE #================================================= ynh_script_progression --message="Starting a systemd service..." --weight=2 -# Reload services -#systemctl enable cockpit.socket --quiet -#ynh_systemd_action --service_name=cockpit.socket --action=start - -#================================================= -# ADVERTISE SERVICE IN ADMIN PANEL -#================================================= - -yunohost service add cockpit.socket --description="Monitor" #--log="/var/log/syslog" - ynh_systemd_action --service_name=cockpit.socket --action="start" --log_path="/var/log/$app/$app.log" -#================================================= -# SETUP SSOWAT -#================================================= -# ynh_script_progression --message="Configuring SSOwat..." --weight=1 - -# # Make app public if necessary or protect it -# if [ $is_public -eq 1 ] -# then -# ynh_permission_update --permission "main" --add "visitors" -# fi - #================================================= # RELOAD NGINX #================================================= diff --git a/scripts/remove b/scripts/remove index a327b7a..09dbbb7 100644 --- a/scripts/remove +++ b/scripts/remove @@ -30,7 +30,7 @@ final_path=$(ynh_app_setting_get $app final_path) if ynh_exec_warn_less yunohost service status $app >/dev/null then ynh_script_progression --message="Removing $app service..." --weight=1 - yunohost service remove $app + yunohost service remove cockpit.socket fi #================================================= @@ -49,14 +49,6 @@ ynh_script_progression --message="Removing dependencies..." --weight=1 # Remove metapackage and its dependencies ynh_remove_app_dependencies -#================================================= -# REMOVE APP MAIN DIR -#================================================= -# ynh_print_info "Removing app main directory" - -# # Remove the app directory securely -# ynh_secure_remove "$final_path" - #================================================= # REMOVE NGINX CONFIGURATION #================================================= From 3cbb950504fac3afeda7d34c472fea020a9fad72 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Mon, 6 Dec 2021 23:14:43 +0100 Subject: [PATCH 18/25] Update install --- scripts/install | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/scripts/install b/scripts/install index 87b5f56..f9a3e89 100644 --- a/scripts/install +++ b/scripts/install @@ -22,25 +22,16 @@ ynh_abort_if_errors # Retrieve arguments domain=$YNH_APP_ARG_DOMAIN path_url=$YNH_APP_ARG_PATH -is_public=$YNH_APP_ARG_IS_PUBLIC app=$YNH_APP_INSTANCE_NAME #================================================= # CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS #================================================= -# ynh_script_progression --message="Validating installation parameters..." --weight=1 +ynh_script_progression --message="Validating installation parameters..." --weight=1 -# final_path=/var/www/$app -# test ! -e "$final_path" || ynh_die "This path already contains a folder" - -# # Normalize the url path syntax -# path_url=$(ynh_normalize_url_path $path_url) - -# # Check web path availability -# ynh_webpath_available $domain $path_url -# # Register (book) web path -# ynh_webpath_register $app $domain $path_url +# Register (book) web path +ynh_webpath_register --app=$app --domain=$domain --path_url=$path_url #================================================= # STORE SETTINGS FROM MANIFEST From c5402814aad83e63e9a46662ac10e6aedb69bfdf Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Mon, 6 Dec 2021 23:17:42 +0100 Subject: [PATCH 19/25] Update install --- scripts/install | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/install b/scripts/install index f9a3e89..ae0e14e 100644 --- a/scripts/install +++ b/scripts/install @@ -79,15 +79,16 @@ ynh_add_nginx_config #================================================= ynh_script_progression --message="Integrating service in YunoHost..." --weight=1 -yunohost service add cockpit.socket --description="Monitor" --log="/var/log/$app/$app.log" +#yunohost service add cockpit.socket --description="Monitor" --log="/var/log/$app/$app.log" #================================================= # START SYSTEMD SERVICE #================================================= ynh_script_progression --message="Starting a systemd service..." --weight=2 -ynh_systemd_action --service_name=cockpit.socket --action="start" --log_path="/var/log/$app/$app.log" - +#ynh_systemd_action --service_name=cockpit.socket --action="start" --log_path="/var/log/$app/$app.log" +systemctl enable cockpit.socket +systemctl start cockpit.socket #================================================= # RELOAD NGINX #================================================= From 517e5996aca6551f7b014331022a92fe8802edf4 Mon Sep 17 00:00:00 2001 From: yalh76 Date: Sun, 13 Mar 2022 21:51:45 +0100 Subject: [PATCH 20/25] Apply example_ynh --- .github/ISSUE_TEMPLATE.md | 55 ++++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 16 ++++ check_process | 5 +- conf/cockpit.conf | 4 - doc/DESCRIPTION.md | 3 +- manifest.json | 6 +- scripts/backup | 9 +- scripts/change_url | 139 +++++++++++++++++++++++++++++++ scripts/install | 37 ++++---- scripts/remove | 40 +++++---- scripts/restore | 41 ++++----- scripts/upgrade | 47 ++++++++--- 12 files changed, 320 insertions(+), 82 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 scripts/change_url diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..2729a6b --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,55 @@ +--- +name: Bug report +about: When creating a bug report, please use the following template to provide all the relevant information and help debugging efficiently. + +--- + +**How to post a meaningful bug report** +1. *Read this whole template first.* +2. *Determine if you are on the right place:* + - *If you were performing an action on the app from the webadmin or the CLI (install, update, backup, restore, change_url...), you are on the right place!* + - *Otherwise, the issue may be due to the app itself. Refer to its documentation or repository for help.* + - *When in doubt, post here and we will figure it out together.* +3. *Delete the italic comments as you write over them below, and remove this guide.* +--- + +### Describe the bug + +*A clear and concise description of what the bug is.* + +### Context + +- Hardware: *VPS bought online / Old laptop or computer / Raspberry Pi at home / Internet Cube with VPN / Other ARM board / ...* +- YunoHost version: x.x.x +- I have access to my server: *Through SSH | through the webadmin | direct access via keyboard / screen | ...* +- Are you in a special context or did you perform some particular tweaking on your YunoHost instance?: *no / yes* + - If yes, please explain: +- Using, or trying to install package version/branch: +- If upgrading, current package version: *can be found in the admin, or with `yunohost app info $app_id`* + +### Steps to reproduce + +- *If you performed a command from the CLI, the command itself is enough. For example:* + ```sh + sudo yunohost app install the_app + ``` +- *If you used the webadmin, please perform the equivalent command from the CLI first.* +- *If the error occurs in your browser, explain what you did:* + 1. *Go to '...'* + 2. *Click on '...'* + 3. *Scroll down to '...'* + 4. *See error* + +### Expected behavior + +*A clear and concise description of what you expected to happen. You can remove this section if the command above is enough to understand your intent.* + +### Logs + +*When an operation fails, YunoHost provides a simple way to share the logs.* +- *In the webadmin, the error message contains a link to the relevant log page. On that page, you will be able to 'Share with Yunopaste'. If you missed it, the logs of previous operations are also available under Tools > Logs.* +- *In command line, the command to share the logs is displayed at the end of the operation and looks like `yunohost log display [log name] --share`. If you missed it, you can find the log ID of a previous operation using `yunohost log list`.* + +*After sharing the log, please copypaste directly the link provided by YunoHost (to help readability, no need to copypaste the entire content of the log here, just the link is enough...)* + +*If applicable and useful, add screenshots to help explain your problem.* diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..ef70e18 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,16 @@ +## Problem + +- *Description of why you made this PR* + +## Solution + +- *And how do you fix that problem* + +## PR Status + +- [ ] Code finished and ready to be reviewed/tested +- [ ] The fix/enhancement were manually tested (if applicable) + +## Automatic tests + +Automatic tests can be triggered on https://ci-apps-dev.yunohost.org/ *after creating the PR*, by commenting "!testme", "!gogogadgetoci" or "By the power of systemd, I invoke The Great App CI to test this Pull Request!". (N.B. : for this to work you need to be a member of the Yunohost-Apps organization) diff --git a/check_process b/check_process index 057ec49..6b536e2 100644 --- a/check_process +++ b/check_process @@ -1,16 +1,13 @@ ;; Test complet ; Manifest domain="domain.tld" - path="/" - is_public=1 - port="9090" ; Checks pkg_linter=1 setup_sub_dir=0 setup_root=1 setup_nourl=0 setup_private=0 - setup_public=1 + setup_public=0 upgrade=1 backup_restore=1 multi_instance=0 diff --git a/conf/cockpit.conf b/conf/cockpit.conf index 4adb59a..363e627 100644 --- a/conf/cockpit.conf +++ b/conf/cockpit.conf @@ -1,7 +1,3 @@ -[WebService] -Origins = https://__DOMAIN__ -https://127.0.0.1:9090 - [WebService] ProtocolHeader = X-Forwarded-Proto diff --git a/doc/DESCRIPTION.md b/doc/DESCRIPTION.md index d33d446..39c4d8d 100644 --- a/doc/DESCRIPTION.md +++ b/doc/DESCRIPTION.md @@ -1 +1,2 @@ -Cockpit is a web-based graphical interface for servers, intended for everyone. \ No newline at end of file +Cockpit is a web-based graphical interface for servers, intended for everyone. + diff --git a/manifest.json b/manifest.json index 5f88acf..3fbccec 100644 --- a/manifest.json +++ b/manifest.json @@ -11,7 +11,8 @@ "upstream": { "license": "LGPL-2.1-only", "website": "https://cockpit-project.org/", - "admindoc": "https://cockpit-project.org/documentation.html" + "admindoc": "https://cockpit-project.org/documentation.html", + "code": "https://github.com/cockpit-project/cockpit" }, "license": "LGPL-2.1-only", "maintainer": { @@ -26,7 +27,8 @@ "nginx" ], "arguments": { - "install": [{ + "install": [ + { "name": "domain", "type": "domain" }, diff --git a/scripts/backup b/scripts/backup index b8c5fad..5bbfcd7 100644 --- a/scripts/backup +++ b/scripts/backup @@ -6,6 +6,7 @@ # 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 @@ -14,7 +15,7 @@ source /usr/share/yunohost/helpers #================================================= ynh_clean_setup () { - ynh_clean_check_starting + true } # Exit if an error occurs during the execution of the script ynh_abort_if_errors @@ -43,13 +44,13 @@ ynh_backup --src_path="/etc/nginx/conf.d/$domain.d/$app.conf" #================================================= # SPECIFIC BACKUP #================================================= -# BACKUP SYSTEMD +# BACKUP VARIOUS FILES #================================================= -ynh_backup --src_path="/etc/systemd/system/$app.service" +ynh_backup --src_path="/etc/cockpit/cockpit.conf" #================================================= # END OF SCRIPT #================================================= -ynh_print_info --message="Backup script completed for cockpit. (YunoHost will then actually copy those files to the archive)." +ynh_print_info --message="Backup script completed for $app. (YunoHost will then actually copy those files to the archive)." diff --git a/scripts/change_url b/scripts/change_url new file mode 100644 index 0000000..139a41c --- /dev/null +++ b/scripts/change_url @@ -0,0 +1,139 @@ +#!/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..." + +# 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) + +#================================================= +# BACKUP BEFORE CHANGE URL THEN ACTIVE TRAP +#================================================= +ynh_script_progression --message="Backing up the app before changing its URL (may take a while)..." + +# Backup the current version of the app +ynh_backup_before_upgrade +ynh_clean_setup () { + ynh_clean_check_starting + # Remove the new domain config file, the remove script won't do it as it doesn't know yet its location. + ynh_secure_remove --file="/etc/nginx/conf.d/$new_domain.d/$app.conf" + + # Restore it if the upgrade fails + ynh_restore_upgradebackup +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# 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..." + +ynh_systemd_action --service_name=$app --action="stop" --log_path="systemd" + +#================================================= +# MODIFY URL IN NGINX CONF +#================================================= +ynh_script_progression --message="Updating NGINX web server configuration..." + +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 +#================================================= +# UPDATE A CONFIG FILE +#================================================= +ynh_script_progression --message="Updating a configuration file..." + +ynh_add_config --template="../conf/cockpit.conf" --destination="/etc/cockpit/cockpit.conf" + +#================================================= +# GENERIC FINALISATION +#================================================= +# START SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Starting a systemd service..." + +# Start a systemd service +ynh_systemd_action --service_name=$app --action="start" --log_path="systemd" --line_match="Started" + +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Change of URL completed for $app" diff --git a/scripts/install b/scripts/install index ae0e14e..437ee60 100644 --- a/scripts/install +++ b/scripts/install @@ -19,7 +19,6 @@ ynh_abort_if_errors # RETRIEVE ARGUMENTS FROM THE MANIFEST #================================================= -# Retrieve arguments domain=$YNH_APP_ARG_DOMAIN path_url=$YNH_APP_ARG_PATH @@ -46,10 +45,10 @@ ynh_app_setting_set --app=$app --key=path --value=$path_url #================================================= # FIND AND OPEN A PORT #================================================= -ynh_script_progression --message="Configuring firewall..." --weight=2 +ynh_script_progression --message="Finding an available port..." --weight=2 # Find an available port -port=$(ynh_find_port --port=9090) +port=$(ynh_find_port --port=8095) ynh_app_setting_set --app=$app --key=port --value=$port #================================================= @@ -59,13 +58,6 @@ ynh_script_progression --message="Installing dependencies..." --weight=20 ynh_exec_warn_less ynh_install_app_dependencies $pkg_dependencies -#================================================= -# ADD A CONFIGURATION -#================================================= -ynh_script_progression --message="Adding a configuration file..." --weight=1 - -ynh_add_config --template="../conf/cockpit.conf" --destination="/etc/cockpit/cockpit.conf" - #================================================= # NGINX CONFIGURATION #================================================= @@ -74,21 +66,38 @@ ynh_script_progression --message="Configuring NGINX web server..." --weight=2 # Create a dedicated NGINX config ynh_add_nginx_config +#================================================= +# SPECIFIC SETUP +#================================================= +# ADD A CONFIGURATION +#================================================= +ynh_script_progression --message="Adding a configuration file..." --weight=1 + +ynh_replace_string --match_string="ListenStream=.*" --replace_string="ListenStream=$port" --target_file="/lib/systemd/system/cockpit.socket" +systemctl daemon-reload +systemctl restart $app.socket + +ynh_add_config --template="../conf/cockpit.conf" --destination="/etc/cockpit/cockpit.conf" + +chmod 440 "/etc/cockpit/cockpit.conf" +chown root:$app-ws "/etc/cockpit/cockpit.conf" + +#================================================= +# GENERIC FINALIZATION #================================================= # INTEGRATE SERVICE IN YUNOHOST #================================================= ynh_script_progression --message="Integrating service in YunoHost..." --weight=1 -#yunohost service add cockpit.socket --description="Monitor" --log="/var/log/$app/$app.log" +yunohost service add $app #================================================= # START SYSTEMD SERVICE #================================================= ynh_script_progression --message="Starting a systemd service..." --weight=2 -#ynh_systemd_action --service_name=cockpit.socket --action="start" --log_path="/var/log/$app/$app.log" -systemctl enable cockpit.socket -systemctl start cockpit.socket +ynh_systemd_action --service_name=$app --action="restart" --log_path="systemd" --line_match="Started" + #================================================= # RELOAD NGINX #================================================= diff --git a/scripts/remove b/scripts/remove index 09dbbb7..028e55b 100644 --- a/scripts/remove +++ b/scripts/remove @@ -12,13 +12,13 @@ source /usr/share/yunohost/helpers #================================================= # LOAD SETTINGS #================================================= -ynh_print_info "Loading installation settings..." +ynh_script_progression --message="Loading installation settings..." app=$YNH_APP_INSTANCE_NAME -domain=$(ynh_app_setting_get $app domain) -port=$(ynh_app_setting_get $app port) -final_path=$(ynh_app_setting_get $app final_path) +domain=$(ynh_app_setting_get --app=$app --key=domain) +port=$(ynh_app_setting_get --app=$app --key=port) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) #================================================= # STANDARD REMOVE @@ -26,11 +26,11 @@ final_path=$(ynh_app_setting_get $app final_path) # REMOVE SERVICE INTEGRATION IN YUNOHOST #================================================= -# Remove the service from the list of services known by Yunohost (added from `yunohost service add`) +# Remove the service from the list of services known by YunoHost (added from `yunohost service add`) if ynh_exec_warn_less yunohost service status $app >/dev/null then ynh_script_progression --message="Removing $app service..." --weight=1 - yunohost service remove cockpit.socket + yunohost service remove $app fi #================================================= @@ -39,15 +39,7 @@ fi ynh_script_progression --message="Stopping and removing the systemd service..." --weight=1 # Remove the dedicated systemd config -ynh_remove_systemd_config - -#================================================= -# REMOVE DEPENDENCIES -#================================================= -ynh_script_progression --message="Removing dependencies..." --weight=1 - -# Remove metapackage and its dependencies -ynh_remove_app_dependencies +ynh_systemd_action --service_name=$app --action="stop" --log_path="systemd" #================================================= # REMOVE NGINX CONFIGURATION @@ -57,6 +49,24 @@ ynh_script_progression --message="Removing NGINX web server configuration..." -- # Remove the dedicated NGINX config ynh_remove_nginx_config +#================================================= +# REMOVE DEPENDENCIES +#================================================= +ynh_script_progression --message="Removing dependencies..." --weight=1 + +# Remove metapackage and its dependencies +ynh_remove_app_dependencies + +#================================================= +# SPECIFIC REMOVE +#================================================= +# REMOVE VARIOUS FILES +#================================================= +ynh_script_progression --message="Removing various files..." + +# Remove a directory securely +ynh_secure_remove --file="/etc/$app" + #================================================= # END OF SCRIPT #================================================= diff --git a/scripts/restore b/scripts/restore index 050f3f8..05b539d 100644 --- a/scripts/restore +++ b/scripts/restore @@ -6,6 +6,7 @@ # 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 @@ -22,26 +23,25 @@ ynh_abort_if_errors #================================================= # LOAD SETTINGS #================================================= -ynh_script_progression --message="Loading settings..." --weight=1 +ynh_script_progression --message="Loading installation settings..." --weight=1 app=$YNH_APP_INSTANCE_NAME domain=$(ynh_app_setting_get --app=$app --key=domain) path_url=$(ynh_app_setting_get --app=$app --key=path) +port=$(ynh_app_setting_get --app=$app --key=port) #================================================= # CHECK IF THE APP CAN BE RESTORED #================================================= ynh_script_progression --message="Validating restoration parameters..." --weight=2 -test ! -d $final_path || ynh_die --message="There is already a directory: $final_path " - #================================================= # STANDARD RESTORATION STEPS #================================================= # RESTORE THE NGINX CONFIGURATION #================================================= -ynh_script_progression --message="Restoring the NGINX configuration..." +ynh_script_progression --message="Restoring the NGINX web server configuration..." ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" @@ -56,41 +56,32 @@ ynh_script_progression --message="Reinstalling dependencies..." --weight=7 ynh_install_app_dependencies $pkg_dependencies #================================================= -# RESTORE SYSTEMD +# RESTORE VARIOUS FILES #================================================= -ynh_script_progression --message="Restoring the systemd configuration..." --weight=5 +ynh_script_progression --message="Restoring various files..." -ynh_restore_file --origin_path="/etc/systemd/system/$app.service" -systemctl enable $app.service +ynh_replace_string --match_string="ListenStream=.*" --replace_string="ListenStream=$port" --target_file="/lib/systemd/system/cockpit.socket" +systemctl daemon-reload +systemctl restart $app.socket + +ynh_restore_file --origin_path="/etc/cockpit/cockpit.conf" #================================================= -# NGINX CONFIGURATION +# INTEGRATE SERVICE IN YUNOHOST #================================================= -ynh_script_progression --message="Configuring NGINX web server..." --weight=2 +ynh_script_progression --message="Integrating service in YunoHost..." --weight=1 -# Create a dedicated NGINX config -ynh_add_nginx_config +yunohost service add $app #================================================= # START SYSTEMD SERVICE #================================================= ynh_script_progression --message="Starting a systemd service..." --weight=2 -# Reload services -ynh_systemd_action --service_name=$app --action="start" -ynh_systemd_action --service_name=$app --action="enable" +ynh_systemd_action --service_name=$app --action="restart" --log_path="systemd" --line_match="Started" #================================================= -# SETUP SSOWAT -#================================================= -ynh_script_progression --message="Configuring SSOwat..." --weight=1 - -# Make app public if necessary or protect it -if [ $is_public -eq 1 ] -then - ynh_permission_update --permission "main" --add "visitors" -fi - +# GENERIC FINALIZATION #================================================= # RELOAD NGINX #================================================= diff --git a/scripts/upgrade b/scripts/upgrade index 84921ee..0f4425f 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -30,12 +30,13 @@ upgrade_type=$(ynh_check_app_version_changed) #================================================= # BACKUP BEFORE UPGRADE THEN ACTIVE TRAP #================================================= -ynh_script_progression --message="Backing up HedgeDoc before upgrading (may take a while)..." --weight=12 +ynh_script_progression --message="Backing up the app before upgrading (may take a while)..." # Backup the current version of the app ynh_backup_before_upgrade ynh_clean_setup () { - # restore it if the upgrade fails + ynh_clean_check_starting + # Restore it if the upgrade fails ynh_restore_upgradebackup } # Exit if an error occurs during the execution of the script @@ -50,13 +51,6 @@ ynh_script_progression --message="Stopping a systemd service..." --weight=1 ynh_systemd_action --service_name=$app --action="stop" --log_path="systemd" -#================================================= -# INSTALL DEPENDENCIES -#================================================= -ynh_script_progression --message="Installing dependencies..." --weight=20 - -ynh_install_app_dependencies $pkg_dependencies - #================================================= # NGINX CONFIGURATION #================================================= @@ -65,14 +59,41 @@ ynh_script_progression --message="Configuring NGINX web server..." --weight=2 # Create a dedicated NGINX config ynh_add_nginx_config +#================================================= +# UPGRADE DEPENDENCIES +#================================================= +ynh_script_progression --message="Upgrading dependencies..." --weight=20 + +ynh_install_app_dependencies $pkg_dependencies + +#================================================= +# SPECIFIC UPGRADE +#================================================= +# UPDATE A CONFIG FILE +#================================================= +ynh_script_progression --message="Updating a configuration file..." --weight=1 + +ynh_replace_string --match_string="ListenStream=.*" --replace_string="ListenStream=$port" --target_file="/lib/systemd/system/cockpit.socket" +systemctl daemon-reload +systemctl restart $app.socket + +ynh_add_config --template="../conf/cockpit.conf" --destination="/etc/cockpit/cockpit.conf" + +#================================================= +# GENERIC FINALIZATION +#================================================= +# INTEGRATE SERVICE IN YUNOHOST +#================================================= +ynh_script_progression --message="Integrating service in YunoHost..." --weight=1 + +yunohost service add $app + #================================================= # START SYSTEMD SERVICE #================================================= ynh_script_progression --message="Starting a systemd service..." --weight=2 -# Reload services -ynh_systemd_action --service_name=$app --action="start" -ynh_systemd_action --service_name=$app --action="enable" +ynh_systemd_action --service_name=$app --action="restart" --log_path="systemd" --line_match="Started" #================================================= # RELOAD NGINX @@ -85,4 +106,4 @@ ynh_systemd_action --service_name=nginx --action=reload # END OF SCRIPT #================================================= -ynh_script_progression --message="Installation of $app completed" --last +ynh_script_progression --message="Upgrade of $app completed" --last From cd3cd18dd4438fe2f8cccd0d226b1a314981553e Mon Sep 17 00:00:00 2001 From: yalh76 Date: Mon, 14 Mar 2022 22:02:10 +0100 Subject: [PATCH 21/25] Fix upgrade --- scripts/upgrade | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/upgrade b/scripts/upgrade index 0f4425f..ebdac3e 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -17,6 +17,7 @@ ynh_script_progression --message="Loading installation settings..." --weight=2 app=$YNH_APP_INSTANCE_NAME domain=$(ynh_app_setting_get --app=$app --key=domain) +path_url=$(ynh_app_setting_get --app=$app --key=path) final_path=$(ynh_app_setting_get --app=$app --key=final_path) port=$(ynh_app_setting_get --app=$app --key=port) From 87f24a40864f28a4b439d7e2f5521148fb081cf9 Mon Sep 17 00:00:00 2001 From: yunohost-bot Date: Mon, 14 Mar 2022 21:02:14 +0000 Subject: [PATCH 22/25] Auto-update README --- README.md | 3 +++ README_fr.md | 3 +++ 2 files changed, 6 insertions(+) diff --git a/README.md b/README.md index 5d95937..b5f117a 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/in Cockpit is a web-based graphical interface for servers, intended for everyone. + + **Shipped version:** 257~ynh1 @@ -29,6 +31,7 @@ Cockpit is a web-based graphical interface for servers, intended for everyone. * Official app website: https://cockpit-project.org/ * Official admin documentation: https://cockpit-project.org/documentation.html +* Upstream app code repository: https://github.com/cockpit-project/cockpit * YunoHost documentation for this app: https://yunohost.org/app_cockpit * Report a bug: https://github.com/YunoHost-Apps/cockpit_ynh/issues diff --git a/README_fr.md b/README_fr.md index b55e13d..0d68f3a 100644 --- a/README_fr.md +++ b/README_fr.md @@ -13,6 +13,8 @@ Si vous n'avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour Cockpit is a web-based graphical interface for servers, intended for everyone. + + **Version incluse :** 257~ynh1 @@ -25,6 +27,7 @@ Cockpit is a web-based graphical interface for servers, intended for everyone. * Site officiel de l'app : https://cockpit-project.org/ * Documentation officielle de l'admin : https://cockpit-project.org/documentation.html +* Dépôt de code officiel de l'app : https://github.com/cockpit-project/cockpit * Documentation YunoHost pour cette app : https://yunohost.org/app_cockpit * Signaler un bug : https://github.com/YunoHost-Apps/cockpit_ynh/issues From 2d9cf5c2082d06539cb7ac0eb50e466c29660a50 Mon Sep 17 00:00:00 2001 From: yalh76 Date: Fri, 18 Mar 2022 00:49:57 +0100 Subject: [PATCH 23/25] Fix version --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index 3fbccec..2a5a79f 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,7 @@ "en": "Sysadmin login session in a web browser", "fr": "Session de connexion sysadmin dans un navigateur Web" }, - "version": "257~ynh1", + "version": "188~ynh1", "url": "https://cockpit-project.org/", "upstream": { "license": "LGPL-2.1-only", From 44191a556fec705024b1b613f1b5389a2c729bf6 Mon Sep 17 00:00:00 2001 From: yunohost-bot Date: Thu, 17 Mar 2022 23:50:01 +0000 Subject: [PATCH 24/25] Auto-update README --- README.md | 2 +- README_fr.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b5f117a..ebfd413 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Cockpit is a web-based graphical interface for servers, intended for everyone. -**Shipped version:** 257~ynh1 +**Shipped version:** 188~ynh1 diff --git a/README_fr.md b/README_fr.md index 0d68f3a..2681e2e 100644 --- a/README_fr.md +++ b/README_fr.md @@ -15,7 +15,7 @@ Cockpit is a web-based graphical interface for servers, intended for everyone. -**Version incluse :** 257~ynh1 +**Version incluse :** 188~ynh1 From 1c0f113ab849c789e3f38eb35db8b265503ac69e Mon Sep 17 00:00:00 2001 From: yalh76 Date: Fri, 18 Mar 2022 16:33:03 +0100 Subject: [PATCH 25/25] Fix path --- conf/cockpit.conf | 4 ++-- conf/nginx.conf | 11 +++-------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/conf/cockpit.conf b/conf/cockpit.conf index 363e627..c6ed880 100644 --- a/conf/cockpit.conf +++ b/conf/cockpit.conf @@ -1,4 +1,4 @@ [WebService] +Origins = https://__DOMAIN__ wss://__DOMAIN__ ProtocolHeader = X-Forwarded-Proto - -UrlRoot = __PATH__/ \ No newline at end of file +UrlRoot = __PATH__ \ No newline at end of file diff --git a/conf/nginx.conf b/conf/nginx.conf index d386d46..cf49999 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,18 +1,13 @@ #sub_path_only rewrite ^__PATH__$ __PATH__/ permanent; -location ^~ __PATH__/ { +location __PATH__/ { - proxy_pass http://127.0.0.1:__PORT__/; + proxy_pass https://127.0.0.1:__PORT____PATH__/; proxy_http_version 1.1; proxy_buffering off; - proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $remote_addr; - - # needed for websocket + proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; - # change scheme of "Origin" to http - proxy_set_header Origin http://$host; # Include SSOWAT user panel.