diff --git a/conf/nginx.conf b/conf/nginx.conf index 86f404e..d023ff8 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,28 +1,26 @@ #sub_path_only rewrite ^__PATH__$ __PATH__/ permanent; -location __PATH__/ { +location ^~ __PATH__/ { + proxy_pass http://127.0.0.1:__PORT__/; + proxy_http_version 1.1; - # Path to source - alias __INSTALL_DIR__/; + proxy_set_header Host 127.0.0.1:__PORT__; + proxy_set_header X-Forwarded-Host $http_host; + proxy_set_header X-Forwarded-For $remote_addr; -### Example PHP configuration (remove it if not used) - index index.php; + # not used by qBittorrent + #proxy_set_header X-Forwarded-Proto $scheme; + #proxy_set_header X-Real-IP $remote_addr; - # Common parameter to increase upload size limit in conjunction with dedicated php-fpm file - #client_max_body_size 50M; + # optionally, you can adjust the POST request size limit, to allow adding a lot of torrents at once + #client_max_body_size 100M; - try_files $uri $uri/ index.php; - location ~ [^/]\.php(/|$) { - fastcgi_split_path_info ^(.+?\.php)(/.*)$; - fastcgi_pass unix:/var/run/php/php__PHPVERSION__-fpm-__NAME__.sock; - - fastcgi_index index.php; - include fastcgi_params; - fastcgi_param REMOTE_USER $remote_user; - fastcgi_param PATH_INFO $fastcgi_path_info; - fastcgi_param SCRIPT_FILENAME $request_filename; - } -### End of PHP configuration part - - # Include SSOWAT user panel. - include conf.d/yunohost_panel.conf.inc; + # Since v4.2.2, is possible to configure qBittorrent + # to set the "Secure" flag for the session cookie automatically. + # However, that option does nothing unless using qBittorrent's built-in HTTPS functionality. + # For this use case, where qBittorrent itself is using plain HTTP + # (and regardless of whether or not the external website uses HTTPS), + # the flag must be set here, in the proxy configuration itself. + # Note: If this flag is set while the external website uses only HTTP, this will cause + # the login mechanism to not work without any apparent errors in console/network resulting in "auth loops". + proxy_cookie_path / "/; Secure"; } diff --git a/conf/systemd.service b/conf/systemd.service index f100e84..6e8a109 100644 --- a/conf/systemd.service +++ b/conf/systemd.service @@ -1,49 +1,17 @@ [Unit] -Description=Small description of the service -After=network.target +Description=qBittorrent-nox service +Documentation=man:qbittorrent-nox(1) +Wants=network-online.target +After=network-online.target nss-lookup.target [Service] -Type=simple +Type=exec User=__APP__ Group=__APP__ WorkingDirectory=__INSTALL_DIR__/ -ExecStart=__INSTALL_DIR__/script -StandardOutput=append:/var/log/__APP__/__APP__.log +ExecStart=/usr/bin/qbittorrent-nox --webui-port=__PORT__ +StandardOutput=append:__INSTALL_DIR__/.local/share/data/qBittorrent/logs/qbittorrent.log StandardError=inherit -# Sandboxing options to harden security -# Depending on specificities of your service/app, you may need to tweak these -# .. but this should be a good baseline -# Details for these options: https://www.freedesktop.org/software/systemd/man/systemd.exec.html -NoNewPrivileges=yes -PrivateTmp=yes -PrivateDevices=yes -RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK -RestrictNamespaces=yes -RestrictRealtime=yes -DevicePolicy=closed -ProtectClock=yes -ProtectHostname=yes -ProtectProc=invisible -ProtectSystem=full -ProtectControlGroups=yes -ProtectKernelModules=yes -ProtectKernelTunables=yes -LockPersonality=yes -SystemCallArchitectures=native -SystemCallFilter=~@clock @debug @module @mount @obsolete @reboot @setuid @swap @cpu-emulation @privileged - -# Denying access to capabilities that should not be relevant for webapps -# Doc: https://man7.org/linux/man-pages/man7/capabilities.7.html -CapabilityBoundingSet=~CAP_RAWIO CAP_MKNOD -CapabilityBoundingSet=~CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_AUDIT_WRITE -CapabilityBoundingSet=~CAP_SYS_BOOT CAP_SYS_TIME CAP_SYS_MODULE CAP_SYS_PACCT -CapabilityBoundingSet=~CAP_LEASE CAP_LINUX_IMMUTABLE CAP_IPC_LOCK -CapabilityBoundingSet=~CAP_BLOCK_SUSPEND CAP_WAKE_ALARM -CapabilityBoundingSet=~CAP_SYS_TTY_CONFIG -CapabilityBoundingSet=~CAP_MAC_ADMIN CAP_MAC_OVERRIDE -CapabilityBoundingSet=~CAP_NET_ADMIN CAP_NET_BROADCAST CAP_NET_RAW -CapabilityBoundingSet=~CAP_SYS_ADMIN CAP_SYS_PTRACE CAP_SYSLOG - [Install] WantedBy=multi-user.target diff --git a/manifest.toml b/manifest.toml index ec46b73..d59e1bd 100644 --- a/manifest.toml +++ b/manifest.toml @@ -1,103 +1,65 @@ packaging_format = 2 -id = "example" -name = "Example app" -description.en = "Explain in *a few (10~15) words* the purpose of the app or what it actually does (it is meant to give a rough idea to users browsing a catalog of 100+ apps)" -description.fr = "Expliquez en *quelques* (10~15) mots l'utilité de l'app ou ce qu'elle fait (l'objectif est de donner une idée grossière pour des utilisateurs qui naviguent dans un catalogue de 100+ apps)" +id = "qbittorrent" +name = "qBittorrent" +description.en = "A bittorrent client that aims to be a good alternative to all other bittorrent clients." +description.fr = "" -version = "1.0~ynh1" +version = "4.2.5~ynh.1" -maintainers = ["johndoe"] +maintainers = ["kay0u"] [upstream] -# NB: Only the "license" key is mandatory. Remove entries for which there's no relevant data -license = "free" -website = "https://example.com" -demo = "https://demo.example.com" -admindoc = "https://yunohost.org/packaging_apps" -userdoc = "https://yunohost.org/apps" -code = "https://some.forge.com/example/example" -# FIXME: optional but recommended if relevant, this is meant to contain the Common Platform Enumeration, which is sort of a standard id for applications defined by the NIST. In particular, YunoHost may use this is in the future to easily track CVE (=security reports) related to apps. The CPE may be obtained by searching here: https://nvd.nist.gov/products/cpe/search. For example, for Nextcloud, the CPE is 'cpe:2.3:a:nextcloud:nextcloud' (no need to include the version number) -cpe = "???" -# FIXME: optional but recommended (or remove if irrelevant / not applicable). This is meant to be an URL where people can financially support this app, especially when its development is based on volunteers and/or financed by its community. YunoHost may later advertise it in the webadmin. -fund = "???" +license = "GPL-3.0-or-later" +website = "hhttps://www.qbittorrent.org" +admindoc = "https://github.com/qbittorrent/qBittorrent/wiki" +code = "https://github.com/qbittorrent/qBittorrent" +cpe = "cpe:2.3:a:qbittorrent:qbittorrent" [integration] -yunohost = ">= 11.1.6" -# FIXME: can be replaced by a list of supported archs using the dpkg --print-architecture nomenclature (amd64/i386/armhf/arm64), for example: ["amd64", "i386"] +yunohost = ">= 11.1.10" architectures = "all" multi_instance = true -# FIXME: replace with true, false, or "not_relevant". Not to confuse with the "sso" key : the "ldap" key corresponds to wether or not a user *can* login on the app using its YunoHost credentials. -ldap = "?" -# FIXME: replace with true, false, or "not_relevant". Not to confuse with the "ldap" key : the "sso" key corresponds to wether or not a user is *automatically logged-in* on the app when logged-in on the YunoHost portal. -sso = "?" -# FIXME: replace with an **estimate** minimum disk and RAM requirements. e.g. 20M, 400M, 1G... +ldap = false +sso = false disk = "50M" ram.build = "50M" ram.runtime = "50M" [install] [install.domain] - # this is a generic question - ask strings are automatically handled by YunoHost's core type = "domain" [install.path] - # this is a generic question - ask strings are automatically handled by YunoHost's core type = "path" - default = "/example" - - [install.init_main_permission] - # this is a generic question - ask strings are automatically handled by YunoHost's core - # This won't be saved as setting and will instead be used to initialize the SSOwat permission - type = "group" - default = "visitors" - - [install.language] - ask.en = "Choose the application language" - ask.fr = "Choisissez la langue de l'application" - type = "string" - choices = ["fr", "en"] - default = "fr" + default = "/qbittorrent" [install.admin] - # this is a generic question - ask strings are automatically handled by YunoHost's core type = "user" - [install.password] - # this is a generic question - ask strings are automatically handled by YunoHost's core - # Note that user-provided passwords questions are not automatically saved as setting - help.en = "Use the help field to add an information for the admin about this question." - help.fr = "Utilisez le champ aide pour ajouter une information à l'intention de l'administrateur à propos de cette question." - type = "password" + #[install.init_main_permission] + ## this is a generic question - ask strings are automatically handled by YunoHost's core + ## This won't be saved as setting and will instead be used to initialize the SSOwat permission + #type = "group" + #default = "visitors" + + #[install.password] + ## this is a generic question - ask strings are automatically handled by YunoHost's core + ## Note that user-provided passwords questions are not automatically saved as setting + #help.en = "Use the help field to add an information for the admin about this question." + #help.fr = "Utilisez le champ aide pour ajouter une information à l'intention de l'administrateur à propos de cette question." + #type = "password" [resources] - # See the packaging documentation for the full set - # of explanation regarding the behavior and properties for each of those - [resources.system_user] - # This will provision/deprovision a unix system user [resources.install_dir] - # This will create/remove the install dir as /var/www/$app - # and store the corresponding setting $install_dir - - [resources.data_dir] - # This will create/remove the data dir as /home/yunohost.app/$app - # and store the corresponding setting $data_dir [resources.permissions] - # This will configure SSOwat permission for $domain/$path/ - # The initial allowed group of user is configured via the init_main_permission question (public=visitors, private=all_users) main.url = "/" [resources.ports] - # This will pick a random port for reverse-proxying and store it as the $port setting + main.default = 30000 [resources.apt] - # This will automatically install/uninstall the following apt packages - # and implicitly define the $phpversion setting as 8.0 (if phpX.Y-foobar dependencies are listed) - packages = "deb1, deb2, php8.0-foo, php8.0-bar" - - [resources.database] - # This will automatically provision/deprovison a mysql DB and store the corresponding credentials in settings $db_user, $db_name, $db_pwd - type = "mysql" + packages = "qbittorrent-nox" diff --git a/scripts/install b/scripts/install index 4ffc34e..5b5cb87 100755 --- a/scripts/install +++ b/scripts/install @@ -9,169 +9,35 @@ source _common.sh source /usr/share/yunohost/helpers -# Install parameters are automatically saved as settings -# -# Settings are automatically loaded as bash variables -# in every app script context, therefore typically these will exist: -# - $domain -# - $path -# - $language -# ... etc -# -# Resources defined in the manifest are provisioned prior to this script -# and corresponding settings are also available, such as: -# - $install_dir -# - $port -# - $db_name -# ... - -# -# $app is the app id (i.e. 'example' for first install, -# or 'example__2', '__3', ... for multi-instance installs) -# - -#================================================= -# APP "BUILD" (DEPLOYING SOURCES, VENV, COMPILING ETC) -#================================================= -# DOWNLOAD, CHECK AND UNPACK SOURCE -#================================================= -ynh_script_progression --message="Setting up source files..." --weight=1 - -### `ynh_setup_source` is used to install an app from a zip or tar.gz file, -### downloaded from an upstream source, like a git repository. -### `ynh_setup_source` use the file conf/app.src - -# Download, check integrity, uncompress and patch the source from app.src -ynh_setup_source --dest_dir="$install_dir" - -# $install_dir will automatically be initialized with some decent -# permission by default ... however, you may need to recursively reapply -# ownership to all files such as after the ynh_setup_source step -chown -R $app:www-data "$install_dir" - #================================================= # SYSTEM CONFIGURATION #================================================= ynh_script_progression --message="Adding system configurations related to $app ..." --weight=1 -### `ynh_add_fpm_config` is used to set up a PHP config. -### You can remove it if your app doesn't use PHP. -### `ynh_add_fpm_config` will use the files conf/php-fpm.conf -### If you're not using these lines: -### - You can remove these files in conf/. -### - Remove the section "BACKUP THE PHP-FPM CONFIGURATION" in the backup script -### - Remove also the section "REMOVE PHP-FPM CONFIGURATION" in the remove script -### - As well as the section "RESTORE THE PHP-FPM CONFIGURATION" in the restore script -### with the reload at the end of the script. -### - And the section "PHP-FPM CONFIGURATION" in the upgrade script - -# Create a dedicated PHP-FPM config using the conf/php-fpm.conf or conf/extra_php-fpm.conf -ynh_add_fpm_config - # Create a dedicated NGINX config using the conf/nginx.conf template ynh_add_nginx_config -### `ynh_systemd_config` is used to configure a systemd script for an app. -### It can be used for apps that use sysvinit (with adaptation) or systemd. -### Have a look at the app to be sure this app needs a systemd script. -### `ynh_systemd_config` will use the file conf/systemd.service -### If you're not using these lines: -### - You can remove those files in conf/. -### - Remove the section "BACKUP SYSTEMD" in the backup script -### - Remove also the section "STOP AND REMOVE SERVICE" in the remove script -### - As well as the section "RESTORE SYSTEMD" in the restore script -### - And the section "SETUP SYSTEMD" in the upgrade script - # Create a dedicated systemd config ynh_add_systemd_config -### `yunohost service add` integrates a service in YunoHost. It then gets -### displayed in the admin interface and through the others `yunohost service` commands. -### (N.B.: this line only makes sense if the app adds a service to the system!) -### If you're not using these lines: -### - You can remove these files in conf/. -### - Remove the section "REMOVE SERVICE INTEGRATION IN YUNOHOST" in the remove script -### - As well as the section "INTEGRATE SERVICE IN YUNOHOST" in the restore script -### - And the section "INTEGRATE SERVICE IN YUNOHOST" in the upgrade script - -yunohost service add $app --description="A short description of the app" --log="/var/log/$app/$app.log" - -### Additional options starting with 3.8: -### -### --needs_exposed_ports "$port" a list of ports that needs to be publicly exposed -### which will then be checked by YunoHost's diagnosis system -### (N.B. DO NOT USE THIS is the port is only internal!!!) -### -### --test_status "some command" a custom command to check the status of the service -### (only relevant if 'systemctl status' doesn't do a good job) -### -### --test_conf "some command" some command similar to "nginx -t" that validates the conf of the service -### -### Re-calling 'yunohost service add' during the upgrade script is the right way -### to proceed if you later realize that you need to enable some flags that -### weren't enabled on old installs (be careful it'll override the existing -### service though so you should re-provide all relevant flags when doing so) - -### `ynh_use_logrotate` is used to configure a logrotate configuration for the logs of this app. -### Use this helper only if there is effectively a log file for this app. -### If you're not using this helper: -### - Remove the section "BACKUP LOGROTATE" in the backup script -### - Remove also the section "REMOVE LOGROTATE CONFIGURATION" in the remove script -### - As well as the section "RESTORE THE LOGROTATE CONFIGURATION" in the restore script -### - And the section "SETUP LOGROTATE" in the upgrade script +yunohost service add $app --description="qBittorrent-nox service" --log="$install_dir/.local/share/data/qBittorrent/logs/qbittorrent.log" # Use logrotate to manage application logfile(s) ynh_use_logrotate # Create a dedicated Fail2Ban config -ynh_add_fail2ban_config --logpath="/var/log/nginx/${domain}-error.log" --failregex="Regex to match into the log for a failed login" +ynh_add_fail2ban_config --logpath="$install_dir/.local/share/data/qBittorrent/logs/qbittorrent.log" --failregex="^.*WebAPI login failure. Reason: invalid credentials, attempt count: .*, IP: .*$" --max_retry=5 #================================================= -# APP INITIAL CONFIGURATION +# YUNOHOST MULTIMEDIA INTEGRATION #================================================= -# ADD A CONFIGURATION -#================================================= -ynh_script_progression --message="Adding a configuration file..." --weight=1 +ynh_script_progression --message="Adding multimedia directories..." --weight=6 -### You can add specific configuration files. -### -### Typically, put your template conf file in ../conf/your_config_file -### The template may contain strings such as __FOO__ or __FOO_BAR__, -### which will automatically be replaced by the values of $foo and $foo_bar -### -### ynh_add_config will also keep track of the config file's checksum, -### which later during upgrade may allow to automatically backup the config file -### if it's found that the file was manually modified -### -### Check the documentation of `ynh_add_config` for more info. +# Build YunoHost multimedia directories +ynh_multimedia_build_main_dir -ynh_add_config --template="some_config_file" --destination="$install_dir/some_config_file" - -# FIXME: this should be handled by the core in the future -# You may need to use chmod 600 instead of 400, -# for example if the app is expected to be able to modify its own config -chmod 400 "$install_dir/some_config_file" -chown $app:$app "$install_dir/some_config_file" - -### For more complex cases where you want to replace stuff using regexes, -### you shoud rely on ynh_replace_string (which is basically a wrapper for sed) -### When doing so, you also need to manually call ynh_store_file_checksum -### -### ynh_replace_string --match_string="match_string" --replace_string="replace_string" --target_file="$install_dir/some_config_file" -### ynh_store_file_checksum --file="$install_dir/some_config_file" - -#================================================= -# SETUP APPLICATION WITH CURL -#================================================= - -### Use these lines only if the app installation needs to be finalized through -### web forms. We generally don't want to ask the final user, -### so we're going to use curl to automatically fill the fields and submit the -### forms. - -# Installation with curl -ynh_script_progression --message="Finalizing installation..." --weight=1 -ynh_local_curl "/INSTALL_PATH" "key1=value1" "key2=value2" "key3=value3" +# Allow nextcloud to write into these directories +ynh_multimedia_addaccess $app #================================================= # GENERIC FINALIZATION @@ -180,16 +46,8 @@ ynh_local_curl "/INSTALL_PATH" "key1=value1" "key2=value2" "key3=value3" #================================================= ynh_script_progression --message="Starting a systemd service..." --weight=1 -### `ynh_systemd_action` is used to start a systemd service for an app. -### Only needed if you have configure a systemd service -### If you're not using these lines: -### - Remove the section "STOP SYSTEMD SERVICE" and "START SYSTEMD SERVICE" in the backup script -### - As well as the section "START SYSTEMD SERVICE" in the restore script -### - As well as the section"STOP SYSTEMD SERVICE" and "START SYSTEMD SERVICE" in the upgrade script -### - And the section "STOP SYSTEMD SERVICE" and "START SYSTEMD SERVICE" in the change_url script - # Start a systemd service -ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" +ynh_systemd_action --service_name=$app --action=start --line_match="Web UI: Now listening on IP: \*, port: $port" --log_path="$install_dir/.local/share/data/qBittorrent/logs/qbittorrent.log" --timeout=3600 #================================================= # END OF SCRIPT diff --git a/scripts/remove b/scripts/remove index f314aa1..701875d 100755 --- a/scripts/remove +++ b/scripts/remove @@ -9,19 +9,6 @@ source _common.sh source /usr/share/yunohost/helpers -# Settings are automatically loaded as bash variables -# in every app script context, therefore typically these will exist: -# - $domain -# - $path -# - $language -# - $install_dir -# - $port -# ... - -# For remove operations : -# - the core will deprovision every resource defined in the manifest **after** this script is ran -# this includes removing the install directory, and data directory (if --purge was used) - #================================================= # REMOVE SYSTEM CONFIGURATIONS #================================================= @@ -43,20 +30,10 @@ ynh_remove_systemd_config ynh_remove_nginx_config -ynh_remove_fpm_config - ynh_remove_logrotate ynh_remove_fail2ban_config -# Remove other various files specific to the app... such as : - -ynh_secure_remove --file="/etc/cron.d/$app" - -ynh_secure_remove --file="/etc/$app" - -ynh_secure_remove --file="/var/log/$app" - #================================================= # END OF SCRIPT #================================================= diff --git a/tests.toml b/tests.toml new file mode 100644 index 0000000..cbbeef1 --- /dev/null +++ b/tests.toml @@ -0,0 +1,3 @@ +test_format = 1.0 + +[default]