diff --git a/.github/workflows/updater.sh b/.github/workflows/updater.sh index b33b480..20198ca 100755 --- a/.github/workflows/updater.sh +++ b/.github/workflows/updater.sh @@ -14,8 +14,8 @@ #================================================= # Fetching information -current_version=$(cat manifest.json | jq -j '.version|split("~")[0]') -repo=$(cat manifest.json | jq -j '.upstream.code|split("https://github.com/")[1]') +current_version=$(cat manifest.toml | tomlq -j '.version|split("~")[0]') +repo=$(cat manifest.toml | tomlq -j '.upstream.code|split("https://github.com/")[1]') # Some jq magic is needed, because the latest upstream release is not always the latest version (e.g. security patches for older versions) version_raw=$(curl --silent "https://api.github.com/repos/$repo/commits/master" | jq -r ".commit.author.date") version=$(date -d "$version_raw" +%Y.%m.%d.%H.%M.%S) @@ -43,42 +43,19 @@ fi # UPDATE SOURCE FILES #================================================= -asset_url="https://github.com/$repo/archive/$commit_hash/master.zip" -# Create the temporary directory -tempdir="$(mktemp -d)" - -# Download sources and calculate checksum -curl --silent -4 -L $asset_url -o "$tempdir/master.zip" -checksum=$(sha256sum "$tempdir/master.zip" | head -c 64) - -# Delete temporary directory -rm -rf $tempdir - -# Rewrite source file -cat < conf/app.src -SOURCE_URL=$asset_url -SOURCE_SUM=$checksum -SOURCE_SUM_PRG=sha256sum -SOURCE_FORMAT=zip -SOURCE_IN_SUBDIR=true -SOURCE_FILENAME=searxng.zip -SOURCE_EXTRACT=true -EOT -echo "... conf/$src.src updated" - #================================================= # SPECIFIC UPDATE STEPS #================================================= -# Any action on the app's source code can be done. -# The GitHub Action workflow takes care of committing all changes after this script ends. +# Replace new version in _common.sh +sed -i "s/^commit_sha=.*/commit_sha=$commit_hash/" scripts/_common.sh #================================================= # GENERIC FINALIZATION #================================================= # Replace new version in manifest -echo "$(jq -s --indent 4 ".[] | .version = \"$version~ynh1\"" manifest.json)" > manifest.json +sed -i "s/^version = .*/version = \"$version~ynh1\"/" manifest.toml # No need to update the README, yunohost-bot takes care of it diff --git a/.github/workflows/updater.yml b/.github/workflows/updater.yml index 2d24728..67b65ad 100644 --- a/.github/workflows/updater.yml +++ b/.github/workflows/updater.yml @@ -17,6 +17,11 @@ jobs: uses: actions/checkout@v3 with: token: ${{ secrets.GITHUB_TOKEN }} + - name: Install python + uses: actions/setup-python@v4 + - name: Install yq/tomlq + id: install_yq + run: pip install yq - name: Run the updater script id: run_updater run: | @@ -36,7 +41,25 @@ jobs: uses: peter-evans/create-pull-request@v4 with: token: ${{ secrets.GITHUB_TOKEN }} - commit-message: Update to version ${{ env.VERSION }} + commit-message: Update testing to version ${{ env.VERSION }} + committer: 'yunohost-bot ' + author: 'yunohost-bot ' + signoff: false + base: testing + branch: ci-auto-update-v${{ env.VERSION }} + delete-branch: true + title: 'Upgrade to version ${{ env.VERSION }}' + body: | + Upgrade to v${{ env.VERSION }} + [See upstream release page](https://github.com/${{ env.REPO }}/releases/tag/v${{ env.VERSION }}) + draft: false + - name: Create Pull Request + id: cpr + if: ${{ env.PROCEED == 'true' }} + uses: peter-evans/create-pull-request@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: Update master to version ${{ env.VERSION }} committer: 'yunohost-bot ' author: 'yunohost-bot ' signoff: false diff --git a/README.md b/README.md index 9c774f4..582c97f 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/in SearxXNG is a free internet metasearch engine which aggregates results from more than 70 search services. Users are neither tracked nor profiled. -**Shipped version:** 2023.08.30.14.25.41~ynh1 +**Shipped version:** 2023.09.12.16.01.06~ynh1 **Demo:** https://searx.be/ diff --git a/README_fr.md b/README_fr.md index 4fa9e48..edd5fe4 100644 --- a/README_fr.md +++ b/README_fr.md @@ -19,7 +19,7 @@ Si vous n’avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) po SearxXNG is a free internet metasearch engine which aggregates results from more than 70 search services. Users are neither tracked nor profiled. -**Version incluse :** 2023.08.30.14.25.41~ynh1 +**Version incluse :** 2023.09.12.16.01.06~ynh1 **Démo :** https://searx.be/ diff --git a/check_process b/check_process deleted file mode 100644 index ea3588a..0000000 --- a/check_process +++ /dev/null @@ -1,21 +0,0 @@ -;; Test complet - ; Manifest - domain="domain.tld" - path="/path" - is_public=1 - language="fr" - admin="john" - password="1Strong-Password" - port="666" - ; Checks - pkg_linter=1 - setup_sub_dir=1 - setup_root=1 - setup_nourl=0 - setup_private=1 - setup_public=1 - upgrade=1 - backup_restore=1 - multi_instance=0 - port_already_use=0 - change_url=1 diff --git a/conf/app.src b/conf/app.src deleted file mode 100644 index 9af28bf..0000000 --- a/conf/app.src +++ /dev/null @@ -1,7 +0,0 @@ -SOURCE_URL=https://github.com/searxng/searxng/archive/7af66736c018d4cc6da9331808c32a529ebae7db/master.zip -SOURCE_SUM=6276860845be5d145cf267e40081a5e9dc3e2ddb34e6ac2f7c6b80f63f086d8f -SOURCE_SUM_PRG=sha256sum -SOURCE_FORMAT=zip -SOURCE_IN_SUBDIR=true -SOURCE_FILENAME=searxng.zip -SOURCE_EXTRACT=true diff --git a/conf/nginx.conf b/conf/nginx.conf index 1a9c997..b4b159f 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,7 +1,6 @@ -#sub_path_only rewrite ^__PATH__$ __PATH__/ permanent; location __PATH__/ { - uwsgi_pass unix:///var/run/__NAME__/app.socket; + uwsgi_pass unix:///var/run/__APP__/app.socket; include uwsgi_params; uwsgi_param HTTP_HOST $host; diff --git a/conf/settings.yml b/conf/settings.yml index ed29352..df0f25f 100644 --- a/conf/settings.yml +++ b/conf/settings.yml @@ -1,2059 +1,14 @@ -general: - # Debug mode, only for development - debug: false - # displayed name - instance_name: "SearXNG - __DOMAIN__" - # For example: https://example.com/privacy - privacypolicy_url: false - # use true to use your own donation page written in searx/info/en/donate.md - # use false to disable the donation link - donation_url: https://docs.searxng.org/donate.html - # mailto:contact@example.com - contact_url: false - # record stats - enable_metrics: true +use_default_settings: true -brand: - new_issue_url: https://github.com/searxng/searxng/issues/new - docs_url: https://docs.searxng.org/ - public_instances: https://searx.space - wiki_url: https://github.com/searxng/searxng/wiki - issue_url: https://github.com/searxng/searxng/issues +general: + instance_name: "SearXNG - __DOMAIN__" search: - # Filter results. 0: None, 1: Moderate, 2: Strict - safe_search: 0 - # Existing autocomplete backends: "dbpedia", "duckduckgo", "google", "yandex", - # "seznam", "startpage", "swisscows", "qwant", "wikipedia" - leave blank to turn it off - # by default. - autocomplete: "" - # minimun characters to type before autocompleter starts - autocomplete_min: 4 - # Default search language - leave blank to detect from browser information or - # use codes from 'languages.py' - default_lang: "" - # Available languages - # languages: - # - all - # - en - # - en-US - # - de - # - it-IT - # - fr - # - fr-BE - # ban time in seconds after engine errors - ban_time_on_fail: 5 - # max ban time in seconds after engine errors - max_ban_time_on_fail: 120 - suspended_times: - # Engine suspension time after error (in seconds; set to 0 to disable) - # For error "Access denied" and "HTTP error [402, 403]" - SearxEngineAccessDenied: 86400 - # For error "CAPTCHA" - SearxEngineCaptcha: 86400 - # For error "Too many request" and "HTTP error 429" - SearxEngineTooManyRequests: 3600 - # Cloudflare CAPTCHA - cf_SearxEngineCaptcha: 1296000 - cf_SearxEngineAccessDenied: 86400 - # ReCAPTCHA - recaptcha_SearxEngineCaptcha: 604800 - - # remove format to deny access, use lower case. - # formats: [html, csv, json, rss] - formats: - - html + default_lang: "auto" server: - # If you change port, bind_address or base_url don't forget to rebuild - # instance's environment (make buildenv) - port: 8888 - bind_address: "127.0.0.1" - base_url: __FULL_URL__ # Possible values: false or "https://example.org/location". - limiter: false # rate limit the number of request on the instance, block some bots - - # If your instance owns a /etc/searxng/settings.yml file, then set the following - # values there. - - secret_key: "__SECRET_KEY__" # change this! - # Proxying image results through searx - image_proxy: false - # 1.0 and 1.1 are supported - http_protocol_version: "1.0" - # POST queries are more secure as they don't show up in history but may cause - # problems when using Firefox containers - method: "POST" - default_http_headers: - X-Content-Type-Options: nosniff - X-XSS-Protection: 1; mode=block - X-Download-Options: noopen - X-Robots-Tag: noindex, nofollow - Referrer-Policy: no-referrer - -redis: - # https://redis-py.readthedocs.io/en/stable/connections.html#redis.client.Redis.from_url - url: false + base_url: https://__DOMAIN____PATH__ + secret_key: "__SECRET_KEY__" ui: - # Custom static path - leave it blank if you didn't change - static_path: "" - static_use_hash: false - # Custom templates path - leave it blank if you didn't change - templates_path: "" - # query_in_title: When true, the result page's titles contains the query - # it decreases the privacy, since the browser can records the page titles. - query_in_title: false - # infinite_scroll: When true, automatically loads the next page when scrolling to bottom of the current page. - infinite_scroll: false - # ui theme - default_theme: simple - # center the results ? - center_alignment: false - # URL prefix of the internet archive, don't forgett trailing slash (if needed). - # cache_url: "https://webcache.googleusercontent.com/search?q=cache:" - # Default interface locale - leave blank to detect from browser information or - # use codes from the 'locales' config section default_locale: "" - # Open result links in a new tab by default - # results_on_new_tab: false - theme_args: - # style of simple theme: auto, light, dark - simple_style: auto - -# Lock arbitrary settings on the preferences page. To find the ID of the user -# setting you want to lock, check the ID of the form on the page "preferences". -# -# preferences: -# lock: -# - language -# - autocomplete -# - method -# - query_in_title - -# searx supports result proxification using an external service: -# https://github.com/asciimoo/morty uncomment below section if you have running -# morty proxy the key is base64 encoded (keep the !!binary notation) -# Note: since commit af77ec3, morty accepts a base64 encoded key. -# -# result_proxy: -# url: http://127.0.0.1:3000/ -# # the key is a base64 encoded string, the YAML !!binary prefix is optional -# key: !!binary "your_morty_proxy_key" -# # [true|false] enable the "proxy" button next to each result -# proxify_results: true - -# communication with search engines -# -outgoing: - # default timeout in seconds, can be override by engine - request_timeout: 3.0 - # the maximum timeout in seconds - # max_request_timeout: 10.0 - # suffix of searx_useragent, could contain information like an email address - # to the administrator - useragent_suffix: "" - # The maximum number of concurrent connections that may be established. - pool_connections: 100 - # Allow the connection pool to maintain keep-alive connections below this - # point. - pool_maxsize: 20 - # See https://www.python-httpx.org/http2/ - enable_http2: true - # uncomment below section if you want to use a custom server certificate - # see https://www.python-httpx.org/advanced/#changing-the-verification-defaults - # and https://www.python-httpx.org/compatibility/#ssl-configuration - # verify: ~/.mitmproxy/mitmproxy-ca-cert.cer - # - # uncomment below section if you want to use a proxyq see: SOCKS proxies - # https://2.python-requests.org/en/latest/user/advanced/#proxies - # are also supported: see - # https://2.python-requests.org/en/latest/user/advanced/#socks - # - # proxies: - # all://: - # - http://proxy1:8080 - # - http://proxy2:8080 - # - # using_tor_proxy: true - # - # Extra seconds to add in order to account for the time taken by the proxy - # - # extra_proxy_timeout: 10.0 - # - # uncomment below section only if you have more than one network interface - # which can be the source of outgoing search requests - # - # source_ips: - # - 1.1.1.1 - # - 1.1.1.2 - # - fe80::/126 - -# External plugin configuration, for more details see -# https://docs.searxng.org/dev/plugins.html -# -# plugins: -# - plugin1 -# - plugin2 -# - ... - -# Comment or un-comment plugin to activate / deactivate by default. -# -# enabled_plugins: -# # these plugins are enabled if nothing is configured .. -# - 'Hash plugin' -# - 'Search on category select' -# - 'Self Information' -# - 'Tracker URL remover' -# - 'Ahmia blacklist' # activation depends on outgoing.using_tor_proxy -# # these plugins are disabled if nothing is configured .. -# - 'Hostname replace' # see hostname_replace configuration below -# - 'Open Access DOI rewrite' -# - 'Vim-like hotkeys' -# - 'Tor check plugin' -# # Read the docs before activate: auto-detection of the language could be -# # detrimental to users expectations / users can activate the plugin in the -# # preferences if they want. -# - 'Autodetect search language' - -# Configuration of the "Hostname replace" plugin: -# -# hostname_replace: -# '(.*\.)?youtube\.com$': 'invidious.example.com' -# '(.*\.)?youtu\.be$': 'invidious.example.com' -# '(.*\.)?youtube-noocookie\.com$': 'yotter.example.com' -# '(.*\.)?reddit\.com$': 'teddit.example.com' -# '(.*\.)?redd\.it$': 'teddit.example.com' -# '(www\.)?twitter\.com$': 'nitter.example.com' -# # to remove matching host names from result list, set value to false -# 'spam\.example\.com': false - -checker: - # disable checker when in debug mode - off_when_debug: true - - # use "scheduling: false" to disable scheduling - # scheduling: interval or int - - # to activate the scheduler: - # * uncomment "scheduling" section - # * add "cache2 = name=searxngcache,items=2000,blocks=2000,blocksize=4096,bitmap=1" - # to your uwsgi.ini - - # scheduling: - # start_after: [300, 1800] # delay to start the first run of the checker - # every: [86400, 90000] # how often the checker runs - - # additional tests: only for the YAML anchors (see the engines section) - # - additional_tests: - rosebud: &test_rosebud - matrix: - query: rosebud - lang: en - result_container: - - not_empty - - ['one_title_contains', 'citizen kane'] - test: - - unique_results - - android: &test_android - matrix: - query: ['android'] - lang: ['en', 'de', 'fr', 'zh-CN'] - result_container: - - not_empty - - ['one_title_contains', 'google'] - test: - - unique_results - - # tests: only for the YAML anchors (see the engines section) - tests: - infobox: &tests_infobox - infobox: - matrix: - query: ["linux", "new york", "bbc"] - result_container: - - has_infobox - -categories_as_tabs: - general: - images: - videos: - news: - map: - music: - it: - science: - files: - social media: - -engines: - - name: 9gag - engine: 9gag - shortcut: 9g - disabled: true - - - name: apk mirror - engine: apkmirror - timeout: 4.0 - shortcut: apkm - disabled: true - - - name: apple app store - engine: apple_app_store - shortcut: aps - disabled: true - - # Requires Tor - - name: ahmia - engine: ahmia - categories: onions - enable_http: true - shortcut: ah - - - name: arch linux wiki - engine: archlinux - shortcut: al - - - name: archive is - engine: xpath - search_url: https://archive.is/search/?q={query} - url_xpath: (//div[@class="TEXT-BLOCK"]/a)/@href - title_xpath: (//div[@class="TEXT-BLOCK"]/a) - content_xpath: //div[@class="TEXT-BLOCK"]/ul/li - categories: general - timeout: 7.0 - disabled: true - shortcut: ai - soft_max_redirects: 1 - about: - website: https://archive.is/ - wikidata_id: Q13515725 - official_api_documentation: https://mementoweb.org/depot/native/archiveis/ - use_official_api: false - require_api_key: false - results: HTML - - - name: artic - engine: artic - shortcut: arc - timeout: 4.0 - - - name: arxiv - engine: arxiv - shortcut: arx - timeout: 4.0 - - # tmp suspended: dh key too small - # - name: base - # engine: base - # shortcut: bs - - - name: bandcamp - engine: bandcamp - shortcut: bc - categories: music - - - name: wikipedia - engine: wikipedia - shortcut: wp - base_url: 'https://{language}.wikipedia.org/' - - - name: bing - engine: bing - shortcut: bi - disabled: true - - - name: bing images - engine: bing_images - shortcut: bii - - - name: bing news - engine: bing_news - shortcut: bin - - - name: bing videos - engine: bing_videos - shortcut: biv - - - name: bitbucket - engine: xpath - paging: true - search_url: https://bitbucket.org/repo/all/{pageno}?name={query} - url_xpath: //article[@class="repo-summary"]//a[@class="repo-link"]/@href - title_xpath: //article[@class="repo-summary"]//a[@class="repo-link"] - content_xpath: //article[@class="repo-summary"]/p - categories: [it, repos] - timeout: 4.0 - disabled: true - shortcut: bb - about: - website: https://bitbucket.org/ - wikidata_id: Q2493781 - official_api_documentation: https://developer.atlassian.com/bitbucket - use_official_api: false - require_api_key: false - results: HTML - - - name: btdigg - engine: btdigg - shortcut: bt - - - name: ccc-tv - engine: xpath - paging: false - search_url: https://media.ccc.de/search/?q={query} - url_xpath: //div[@class="caption"]/h3/a/@href - title_xpath: //div[@class="caption"]/h3/a/text() - content_xpath: //div[@class="caption"]/h4/@title - categories: videos - disabled: true - shortcut: c3tv - about: - website: https://media.ccc.de/ - wikidata_id: Q80729951 - official_api_documentation: https://github.com/voc/voctoweb - use_official_api: false - require_api_key: false - results: HTML - # We don't set language: de here because media.ccc.de is not just - # for a German audience. It contains many English videos and many - # German videos have English subtitles. - - - name: openverse - engine: openverse - categories: images - shortcut: opv - - # - name: core.ac.uk - # engine: core - # categories: science - # shortcut: cor - # # get your API key from: https://core.ac.uk/api-keys/register/ - # api_key: 'unset' - - - name: crossref - engine: crossref - shortcut: cr - timeout: 30 - disabled: true - - - name: yep - engine: json_engine - shortcut: yep - categories: general - disabled: true - paging: false - content_html_to_text: true - title_html_to_text: true - search_url: https://api.yep.com/fs/1/?type=web&q={query}&no_correct=false&limit=100 - results_query: 1/results - title_query: title - url_query: url - content_query: snippet - about: - website: https://yep.com - use_official_api: false - require_api_key: false - results: JSON - - - name: curlie - engine: xpath - shortcut: cl - categories: general - disabled: true - paging: true - lang_all: '' - search_url: https://curlie.org/search?q={query}&lang={lang}&start={pageno}&stime=92452189 - page_size: 20 - results_xpath: //div[@id="site-list-content"]/div[@class="site-item"] - url_xpath: ./div[@class="title-and-desc"]/a/@href - title_xpath: ./div[@class="title-and-desc"]/a/div - content_xpath: ./div[@class="title-and-desc"]/div[@class="site-descr"] - about: - website: https://curlie.org/ - wikidata_id: Q60715723 - use_official_api: false - require_api_key: false - results: HTML - - - name: currency - engine: currency_convert - categories: general - shortcut: cc - - - name: deezer - engine: deezer - shortcut: dz - disabled: true - - - name: deviantart - engine: deviantart - shortcut: da - timeout: 3.0 - - - name: ddg definitions - engine: duckduckgo_definitions - shortcut: ddd - weight: 2 - disabled: true - tests: *tests_infobox - - # cloudflare protected - # - name: digbt - # engine: digbt - # shortcut: dbt - # timeout: 6.0 - # disabled: true - - - name: docker hub - engine: docker_hub - shortcut: dh - categories: [it, packages] - - - name: erowid - engine: xpath - paging: true - first_page_num: 0 - page_size: 30 - search_url: https://www.erowid.org/search.php?q={query}&s={pageno} - url_xpath: //dl[@class="results-list"]/dt[@class="result-title"]/a/@href - title_xpath: //dl[@class="results-list"]/dt[@class="result-title"]/a/text() - content_xpath: //dl[@class="results-list"]/dd[@class="result-details"] - categories: [] - shortcut: ew - disabled: true - about: - website: https://www.erowid.org/ - wikidata_id: Q1430691 - official_api_documentation: - use_official_api: false - require_api_key: false - results: HTML - - # - name: elasticsearch - # shortcut: es - # engine: elasticsearch - # base_url: http://localhost:9200 - # username: elastic - # password: changeme - # index: my-index - # # available options: match, simple_query_string, term, terms, custom - # query_type: match - # # if query_type is set to custom, provide your query here - # #custom_query_json: {"query":{"match_all": {}}} - # #show_metadata: false - # disabled: true - - - name: wikidata - engine: wikidata - shortcut: wd - timeout: 3.0 - weight: 2 - tests: *tests_infobox - - - name: duckduckgo - engine: duckduckgo - shortcut: ddg - - - name: duckduckgo images - engine: duckduckgo_images - shortcut: ddi - timeout: 3.0 - disabled: true - - - name: duckduckgo weather - engine: duckduckgo_weather - shortcut: ddw - disabled: true - - - name: apple maps - engine: apple_maps - shortcut: apm - disabled: true - timeout: 5.0 - - - name: emojipedia - engine: emojipedia - timeout: 4.0 - shortcut: em - disabled: true - - - name: tineye - engine: tineye - shortcut: tin - timeout: 9.0 - - - name: etymonline - engine: xpath - paging: true - search_url: https://etymonline.com/search?page={pageno}&q={query} - url_xpath: //a[contains(@class, "word__name--")]/@href - title_xpath: //a[contains(@class, "word__name--")] - content_xpath: //section[contains(@class, "word__defination")] - first_page_num: 1 - shortcut: et - categories: [dictionaries] - disabled: false - about: - website: https://www.etymonline.com/ - wikidata_id: Q1188617 - official_api_documentation: - use_official_api: false - require_api_key: false - results: HTML - - # - name: ebay - # engine: ebay - # shortcut: eb - # base_url: 'https://www.ebay.com' - # disabled: true - # timeout: 5 - - - name: 1x - engine: www1x - shortcut: 1x - timeout: 3.0 - disabled: true - - - name: fdroid - engine: fdroid - shortcut: fd - disabled: true - - - name: flickr - categories: images - shortcut: fl - # You can use the engine using the official stable API, but you need an API - # key, see: https://www.flickr.com/services/apps/create/ - # engine: flickr - # api_key: 'apikey' # required! - # Or you can use the html non-stable engine, activated by default - engine: flickr_noapi - - - name: free software directory - engine: mediawiki - shortcut: fsd - categories: [it, software wikis] - base_url: https://directory.fsf.org/ - number_of_results: 5 - # what part of a page matches the query string: title, text, nearmatch - # * title - query matches title - # * text - query matches the text of page - # * nearmatch - nearmatch in title - search_type: title - timeout: 5.0 - disabled: true - about: - website: https://directory.fsf.org/ - wikidata_id: Q2470288 - - # - name: freesound - # engine: freesound - # shortcut: fnd - # disabled: true - # timeout: 15.0 - # API key required, see: https://freesound.org/docs/api/overview.html - # api_key: MyAPIkey - - - name: frinkiac - engine: frinkiac - shortcut: frk - disabled: true - - - name: genius - engine: genius - shortcut: gen - - - name: gigablast - engine: gigablast - shortcut: gb - timeout: 4.0 - disabled: true - additional_tests: - rosebud: *test_rosebud - - - name: gentoo - engine: gentoo - shortcut: ge - - - name: gitlab - engine: json_engine - paging: true - search_url: https://gitlab.com/api/v4/projects?search={query}&page={pageno} - url_query: web_url - title_query: name_with_namespace - content_query: description - page_size: 20 - categories: [it, repos] - shortcut: gl - timeout: 10.0 - disabled: true - about: - website: https://about.gitlab.com/ - wikidata_id: Q16639197 - official_api_documentation: https://docs.gitlab.com/ee/api/ - use_official_api: false - require_api_key: false - results: JSON - - - name: github - engine: github - shortcut: gh - - # This a Gitea service. If you would like to use a different instance, - # change codeberg.org to URL of the desired Gitea host. Or you can create a - # new engine by copying this and changing the name, shortcut and search_url. - - - name: codeberg - engine: json_engine - search_url: https://codeberg.org/api/v1/repos/search?q={query}&limit=10 - url_query: html_url - title_query: name - content_query: description - categories: [it, repos] - shortcut: cb - disabled: true - about: - website: https://codeberg.org/ - wikidata_id: - official_api_documentation: https://try.gitea.io/api/swagger - use_official_api: false - require_api_key: false - results: JSON - - - name: google - engine: google - shortcut: go - # see https://docs.searxng.org/src/searx.engines.google.html#module-searx.engines.google - use_mobile_ui: false - # additional_tests: - # android: *test_android - - # - name: google italian - # engine: google - # shortcut: goit - # use_mobile_ui: false - # language: it - - # - name: google mobile ui - # engine: google - # shortcut: gomui - # use_mobile_ui: true - - - name: google images - engine: google_images - shortcut: goi - # additional_tests: - # android: *test_android - # dali: - # matrix: - # query: ['Dali Christ'] - # lang: ['en', 'de', 'fr', 'zh-CN'] - # result_container: - # - ['one_title_contains', 'Salvador'] - - - name: google news - engine: google_news - shortcut: gon - # additional_tests: - # android: *test_android - - - name: google videos - engine: google_videos - shortcut: gov - # additional_tests: - # android: *test_android - - - name: google scholar - engine: google_scholar - shortcut: gos - - - name: google play apps - engine: google_play_apps - shortcut: gpa - disabled: true - - - name: google play movies - engine: xpath - send_accept_language_header: true - search_url: https://play.google.com/store/search?q={query}&c=movies - results_xpath: '//div[@class="ImZGtf mpg5gc"]' - title_xpath: './/div[@class="RZEgze"]//div[@class="kCSSQe"]//a' - url_xpath: './/div[@class="RZEgze"]//div[@class="kCSSQe"]//a/@href' - content_xpath: './/div[@class="kCSSQe"]' - thumbnail_xpath: './/div[@class="uzcko"]/div/span[1]//img/@data-src' - categories: videos - shortcut: gpm - disabled: true - about: - website: https://play.google.com/ - wikidata_id: Q79576 - official_api_documentation: - use_official_api: false - require_api_key: false - results: HTML - - - name: gpodder - engine: json_engine - shortcut: gpod - timeout: 4.0 - paging: false - search_url: https://gpodder.net/search.json?q={query} - url_query: url - title_query: title - content_query: description - page_size: 19 - categories: music - disabled: true - about: - website: https://gpodder.net - wikidata_id: Q3093354 - official_api_documentation: https://gpoddernet.readthedocs.io/en/latest/api/ - use_official_api: false - requires_api_key: false - results: JSON - - - name: habrahabr - engine: xpath - paging: true - search_url: https://habrahabr.ru/search/page{pageno}/?q={query} - url_xpath: //article[contains(@class, "post")]//a[@class="post__title_link"]/@href - title_xpath: //article[contains(@class, "post")]//a[@class="post__title_link"] - content_xpath: //article[contains(@class, "post")]//div[contains(@class, "post__text")] - categories: it - timeout: 4.0 - disabled: true - shortcut: habr - about: - website: https://habr.com/ - wikidata_id: Q4494434 - official_api_documentation: https://habr.com/en/docs/help/api/ - use_official_api: false - require_api_key: false - results: HTML - - - name: hoogle - engine: xpath - paging: true - search_url: https://hoogle.haskell.org/?hoogle={query}&start={pageno} - results_xpath: '//div[@class="result"]' - title_xpath: './/div[@class="ans"]//a' - url_xpath: './/div[@class="ans"]//a/@href' - content_xpath: './/div[@class="from"]' - page_size: 20 - categories: [it, packages] - shortcut: ho - about: - website: https://hoogle.haskell.org/ - wikidata_id: Q34010 - official_api_documentation: https://hackage.haskell.org/api - use_official_api: false - require_api_key: false - results: JSON - - - name: imdb - engine: imdb - shortcut: imdb - timeout: 6.0 - disabled: true - - - name: ina - engine: ina - shortcut: in - timeout: 6.0 - disabled: true - - - name: invidious - engine: invidious - # Instanes will be selected randomly, see https://api.invidious.io/ for - # instances that are stable (good uptime) and close to you. - base_url: - - https://invidious.snopyta.org - - https://vid.puffyan.us - # - https://invidious.kavin.rocks # Error 1020 // Access denied by Cloudflare - - https://invidio.xamh.de - - https://inv.riverside.rocks - shortcut: iv - timeout: 3.0 - disabled: true - - - name: jisho - engine: jisho - shortcut: js - timeout: 3.0 - disabled: true - - - name: kickass - engine: kickass - shortcut: kc - timeout: 4.0 - disabled: true - - - name: library genesis - engine: xpath - search_url: https://libgen.fun/search.php?req={query} - url_xpath: //a[contains(@href,"get.php?md5")]/@href - title_xpath: //a[contains(@href,"book/")]/text()[1] - content_xpath: //td/a[1][contains(@href,"=author")]/text() - categories: files - timeout: 7.0 - disabled: true - shortcut: lg - about: - website: https://libgen.fun/ - wikidata_id: Q22017206 - official_api_documentation: - use_official_api: false - require_api_key: false - results: HTML - - # Disabling zlibrary due to z-lib.org domain seizure - # https://github.com/searxng/searxng/pull/1937 - # - # - name: z-library - # engine: zlibrary - # shortcut: zlib - # categories: files - # timeout: 3.0 - # # choose base_url, otherwise engine will do it at initialization time - # # base_url: https://b-ok.cc - # # base_url: https://de1lib.org - # # base_url: https://booksc.eu # does not have cover preview - # # base_url: https://booksc.org # does not have cover preview - - - name: library of congress - engine: loc - shortcut: loc - categories: images - - - name: lingva - engine: lingva - shortcut: lv - # set lingva instance in url, by default it will use the official instance - # url: https://lingva.ml - - - name: lobste.rs - engine: xpath - search_url: https://lobste.rs/search?utf8=%E2%9C%93&q={query}&what=stories&order=relevance - results_xpath: //li[contains(@class, "story")] - url_xpath: .//a[@class="u-url"]/@href - title_xpath: .//a[@class="u-url"] - content_xpath: .//a[@class="domain"] - categories: it - shortcut: lo - timeout: 5.0 - disabled: true - about: - website: https://lobste.rs/ - wikidata_id: Q60762874 - official_api_documentation: - use_official_api: false - require_api_key: false - results: HTML - - - name: azlyrics - shortcut: lyrics - engine: xpath - timeout: 4.0 - disabled: true - categories: [music, lyrics] - paging: true - search_url: https://search.azlyrics.com/search.php?q={query}&w=lyrics&p={pageno} - url_xpath: //td[@class="text-left visitedlyr"]/a/@href - title_xpath: //span/b/text() - content_xpath: //td[@class="text-left visitedlyr"]/a/small - about: - website: https://azlyrics.com - wikidata_id: Q66372542 - official_api_documentation: - use_official_api: false - require_api_key: false - results: HTML - - - name: metacpan - engine: metacpan - shortcut: cpan - disabled: true - number_of_results: 20 - - # - name: meilisearch - # engine: meilisearch - # shortcut: mes - # enable_http: true - # base_url: http://localhost:7700 - # index: my-index - - - name: mixcloud - engine: mixcloud - shortcut: mc - - # MongoDB engine - # Required dependency: pymongo - # - name: mymongo - # engine: mongodb - # shortcut: md - # exact_match_only: false - # host: '127.0.0.1' - # port: 27017 - # enable_http: true - # results_per_page: 20 - # database: 'business' - # collection: 'reviews' # name of the db collection - # key: 'name' # key in the collection to search for - - - name: npm - engine: json_engine - paging: true - first_page_num: 0 - search_url: https://api.npms.io/v2/search?q={query}&size=25&from={pageno} - results_query: results - url_query: package/links/npm - title_query: package/name - content_query: package/description - page_size: 25 - categories: [it, packages] - disabled: true - timeout: 5.0 - shortcut: npm - about: - website: https://npms.io/ - wikidata_id: Q7067518 - official_api_documentation: https://api-docs.npms.io/ - use_official_api: false - require_api_key: false - results: JSON - - - name: nyaa - engine: nyaa - shortcut: nt - disabled: true - - - name: mankier - engine: json_engine - search_url: https://www.mankier.com/api/v2/mans/?q={query} - results_query: results - url_query: url - title_query: name - content_query: description - categories: it - shortcut: man - about: - website: https://www.mankier.com/ - official_api_documentation: https://www.mankier.com/api - use_official_api: true - require_api_key: false - results: JSON - - - name: openairedatasets - engine: json_engine - paging: true - search_url: https://api.openaire.eu/search/datasets?format=json&page={pageno}&size=10&title={query} - results_query: response/results/result - url_query: metadata/oaf:entity/oaf:result/children/instance/webresource/url/$ - title_query: metadata/oaf:entity/oaf:result/title/$ - content_query: metadata/oaf:entity/oaf:result/description/$ - content_html_to_text: true - categories: "science" - shortcut: oad - timeout: 5.0 - about: - website: https://www.openaire.eu/ - wikidata_id: Q25106053 - official_api_documentation: https://api.openaire.eu/ - use_official_api: false - require_api_key: false - results: JSON - - - name: openairepublications - engine: json_engine - paging: true - search_url: https://api.openaire.eu/search/publications?format=json&page={pageno}&size=10&title={query} - results_query: response/results/result - url_query: metadata/oaf:entity/oaf:result/children/instance/webresource/url/$ - title_query: metadata/oaf:entity/oaf:result/title/$ - content_query: metadata/oaf:entity/oaf:result/description/$ - content_html_to_text: true - categories: science - shortcut: oap - timeout: 5.0 - about: - website: https://www.openaire.eu/ - wikidata_id: Q25106053 - official_api_documentation: https://api.openaire.eu/ - use_official_api: false - require_api_key: false - results: JSON - - # - name: opensemanticsearch - # engine: opensemantic - # shortcut: oss - # base_url: 'http://localhost:8983/solr/opensemanticsearch/' - - - name: openstreetmap - engine: openstreetmap - shortcut: osm - - - name: openrepos - engine: xpath - paging: true - search_url: https://openrepos.net/search/node/{query}?page={pageno} - url_xpath: //li[@class="search-result"]//h3[@class="title"]/a/@href - title_xpath: //li[@class="search-result"]//h3[@class="title"]/a - content_xpath: //li[@class="search-result"]//div[@class="search-snippet-info"]//p[@class="search-snippet"] - categories: files - timeout: 4.0 - disabled: true - shortcut: or - about: - website: https://openrepos.net/ - wikidata_id: - official_api_documentation: - use_official_api: false - require_api_key: false - results: HTML - - - name: packagist - engine: json_engine - paging: true - search_url: https://packagist.org/search.json?q={query}&page={pageno} - results_query: results - url_query: url - title_query: name - content_query: description - categories: [it, packages] - disabled: true - timeout: 5.0 - shortcut: pack - about: - website: https://packagist.org - wikidata_id: Q108311377 - official_api_documentation: https://packagist.org/apidoc - use_official_api: true - require_api_key: false - results: JSON - - - name: pdbe - engine: pdbe - shortcut: pdb - # Hide obsolete PDB entries. Default is not to hide obsolete structures - # hide_obsolete: false - - - name: photon - engine: photon - shortcut: ph - - - name: piratebay - engine: piratebay - shortcut: tpb - # You may need to change this URL to a proxy if piratebay is blocked in your - # country - url: https://thepiratebay.org/ - timeout: 3.0 - - # Required dependency: psychopg2 - # - name: postgresql - # engine: postgresql - # database: postgres - # username: postgres - # password: postgres - # limit: 10 - # query_str: 'SELECT * from my_table WHERE my_column = %(query)s' - # shortcut : psql - - - name: pub.dev - engine: xpath - shortcut: pd - search_url: https://pub.dev/packages?q={query}&page={pageno} - paging: true - results_xpath: /html/body/main/div/div[@class="search-results"]/div[@class="packages"]/div - url_xpath: ./div/h3/a/@href - title_xpath: ./div/h3/a - content_xpath: ./p[@class="packages-description"] - categories: [packages, it] - timeout: 3.0 - disabled: true - first_page_num: 1 - about: - website: https://pub.dev/ - official_api_documentation: https://pub.dev/help/api - use_official_api: false - require_api_key: false - results: HTML - - - name: pubmed - engine: pubmed - shortcut: pub - timeout: 3.0 - - - name: pypi - shortcut: pypi - engine: xpath - paging: true - search_url: https://pypi.org/search?q={query}&page={pageno} - results_xpath: /html/body/main/div/div/div/form/div/ul/li/a[@class="package-snippet"] - url_xpath: ./@href - title_xpath: ./h3/span[@class="package-snippet__name"] - content_xpath: ./p - suggestion_xpath: /html/body/main/div/div/div/form/div/div[@class="callout-block"]/p/span/a[@class="link"] - first_page_num: 1 - categories: [it, packages] - about: - website: https://pypi.org - wikidata_id: Q2984686 - official_api_documentation: https://warehouse.readthedocs.io/api-reference/index.html - use_official_api: false - require_api_key: false - results: HTML - - - name: qwant - qwant_categ: web - engine: qwant - shortcut: qw - categories: [general, web] - disabled: false - additional_tests: - rosebud: *test_rosebud - - - name: qwant news - qwant_categ: news - engine: qwant - shortcut: qwn - categories: news - disabled: false - network: qwant - - - name: qwant images - qwant_categ: images - engine: qwant - shortcut: qwi - categories: [images, web] - disabled: false - network: qwant - - - name: qwant videos - qwant_categ: videos - engine: qwant - shortcut: qwv - categories: [videos, web] - disabled: false - network: qwant - - # - name: library - # engine: recoll - # shortcut: lib - # base_url: 'https://recoll.example.org/' - # search_dir: '' - # mount_prefix: /export - # dl_prefix: 'https://download.example.org' - # timeout: 30.0 - # categories: files - # disabled: true - - # - name: recoll library reference - # engine: recoll - # base_url: 'https://recoll.example.org/' - # search_dir: reference - # mount_prefix: /export - # dl_prefix: 'https://download.example.org' - # shortcut: libr - # timeout: 30.0 - # categories: files - # disabled: true - - - name: reddit - engine: reddit - shortcut: re - page_size: 25 - - # Required dependency: redis - # - name: myredis - # shortcut : rds - # engine: redis_server - # exact_match_only: false - # host: '127.0.0.1' - # port: 6379 - # enable_http: true - # password: '' - # db: 0 - - # tmp suspended: bad certificate - # - name: scanr structures - # shortcut: scs - # engine: scanr_structures - # disabled: true - - - name: sepiasearch - engine: sepiasearch - shortcut: sep - - - name: soundcloud - engine: soundcloud - shortcut: sc - - - name: stackoverflow - engine: stackexchange - shortcut: st - api_site: 'stackoverflow' - categories: [it, q&a] - - - name: askubuntu - engine: stackexchange - shortcut: ubuntu - api_site: 'askubuntu' - categories: [it, q&a] - - - name: superuser - engine: stackexchange - shortcut: su - api_site: 'superuser' - categories: [it, q&a] - - - name: searchcode code - engine: searchcode_code - shortcut: scc - disabled: true - - - name: framalibre - engine: framalibre - shortcut: frl - disabled: true - - # - name: searx - # engine: searx_engine - # shortcut: se - # instance_urls : - # - http://127.0.0.1:8888/ - # - ... - # disabled: true - - - name: semantic scholar - engine: semantic_scholar - disabled: true - shortcut: se - - # Spotify needs API credentials - # - name: spotify - # engine: spotify - # shortcut: stf - # api_client_id: ******* - # api_client_secret: ******* - - # - name: solr - # engine: solr - # shortcut: slr - # base_url: http://localhost:8983 - # collection: collection_name - # sort: '' # sorting: asc or desc - # field_list: '' # comma separated list of field names to display on the UI - # default_fields: '' # default field to query - # query_fields: '' # query fields - # enable_http: true - - # - name: springer nature - # engine: springer - # # get your API key from: https://dev.springernature.com/signup - # # working API key, for test & debug: "a69685087d07eca9f13db62f65b8f601" - # api_key: 'unset' - # shortcut: springer - # timeout: 15.0 - - - name: startpage - engine: startpage - shortcut: sp - timeout: 6.0 - disabled: true - additional_tests: - rosebud: *test_rosebud - - - name: tokyotoshokan - engine: tokyotoshokan - shortcut: tt - timeout: 6.0 - disabled: true - - - name: solidtorrents - engine: solidtorrents - shortcut: solid - timeout: 4.0 - disabled: false - base_url: - - https://solidtorrents.net - - https://solidtorrents.eu - - https://solidtorrents.to - - https://bitsearch.to - - # For this demo of the sqlite engine download: - # https://liste.mediathekview.de/filmliste-v2.db.bz2 - # and unpack into searx/data/filmliste-v2.db - # Query to test: "!demo concert" - # - # - name: demo - # engine: sqlite - # shortcut: demo - # categories: general - # result_template: default.html - # database: searx/data/filmliste-v2.db - # query_str: >- - # SELECT title || ' (' || time(duration, 'unixepoch') || ')' AS title, - # COALESCE( NULLIF(url_video_hd,''), NULLIF(url_video_sd,''), url_video) AS url, - # description AS content - # FROM film - # WHERE title LIKE :wildcard OR description LIKE :wildcard - # ORDER BY duration DESC - # disabled: false - - # Requires Tor - - name: torch - engine: xpath - paging: true - search_url: - http://xmh57jrknzkhv6y3ls3ubitzfqnkrwxhopf5aygthi7d6rplyvk3noyd.onion/cgi-bin/omega/omega?P={query}&DEFAULTOP=and - results_xpath: //table//tr - url_xpath: ./td[2]/a - title_xpath: ./td[2]/b - content_xpath: ./td[2]/small - categories: onions - enable_http: true - shortcut: tch - - # torznab engine lets you query any torznab compatible indexer. Using this - # engine in combination with Jackett (https://github.com/Jackett/Jackett) - # opens the possibility to query a lot of public and private indexers directly - # from SearXNG. - # - name: torznab - # engine: torznab - # shortcut: trz - # base_url: http://localhost:9117/api/v2.0/indexers/all/results/torznab - # enable_http: true # if using localhost - # api_key: xxxxxxxxxxxxxxx - # # https://github.com/Jackett/Jackett/wiki/Jackett-Categories - # torznab_categories: # optional - # - 2000 - # - 5000 - - - name: twitter - shortcut: tw - engine: twitter - disabled: true - - # maybe in a fun category - # - name: uncyclopedia - # engine: mediawiki - # shortcut: unc - # base_url: https://uncyclopedia.wikia.com/ - # number_of_results: 5 - - # tmp suspended - too slow, too many errors - # - name: urbandictionary - # engine : xpath - # search_url : https://www.urbandictionary.com/define.php?term={query} - # url_xpath : //*[@class="word"]/@href - # title_xpath : //*[@class="def-header"] - # content_xpath: //*[@class="meaning"] - # shortcut: ud - - - name: unsplash - engine: unsplash - shortcut: us - - - name: yahoo - engine: yahoo - shortcut: yh - disabled: true - - - name: yahoo news - engine: yahoo_news - shortcut: yhn - - - name: youtube - shortcut: yt - # You can use the engine using the official stable API, but you need an API - # key See: https://console.developers.google.com/project - # - # engine: youtube_api - # api_key: 'apikey' # required! - # - # Or you can use the html non-stable engine, activated by default - engine: youtube_noapi - - - name: dailymotion - engine: dailymotion - shortcut: dm - - - name: vimeo - engine: vimeo - shortcut: vm - - - name: wiby - engine: json_engine - paging: true - search_url: https://wiby.me/json/?q={query}&p={pageno} - url_query: URL - title_query: Title - content_query: Snippet - categories: [general, web] - shortcut: wib - disabled: true - about: - website: https://wiby.me/ - - - name: marginalia - engine: json_engine - shortcut: mar - categories: general - paging: false - # index: {"0": "popular", "1": "blogs", "2": "big_sites", - # "3": "default", "4": experimental"} - search_url: https://api.marginalia.nu/public/search/{query}?index=4&count=20 - results_query: results - url_query: url - title_query: title - content_query: description - timeout: 1.5 - disabled: true - about: - website: https://www.marginalia.nu/ - official_api_documentation: https://api.marginalia.nu/ - use_official_api: true - require_api_key: true - results: JSON - - - name: alexandria - engine: json_engine - shortcut: alx - categories: general - paging: true - search_url: https://api.alexandria.org/?a=1&q={query}&p={pageno} - results_query: results - title_query: title - url_query: url - content_query: snippet - timeout: 1.5 - disabled: true - about: - website: https://alexandria.org/ - official_api_documentation: https://github.com/alexandria-org/alexandria-api/raw/master/README.md - use_official_api: true - require_api_key: false - results: JSON - - - name: wikibooks - engine: mediawiki - shortcut: wb - categories: general - base_url: "https://{language}.wikibooks.org/" - number_of_results: 5 - search_type: text - disabled: true - about: - website: https://www.wikibooks.org/ - wikidata_id: Q367 - - - name: wikinews - engine: mediawiki - shortcut: wn - categories: news - base_url: "https://{language}.wikinews.org/" - number_of_results: 5 - search_type: text - disabled: true - about: - website: https://www.wikinews.org/ - wikidata_id: Q964 - - - name: wikiquote - engine: mediawiki - shortcut: wq - categories: general - base_url: "https://{language}.wikiquote.org/" - number_of_results: 5 - search_type: text - disabled: true - additional_tests: - rosebud: *test_rosebud - about: - website: https://www.wikiquote.org/ - wikidata_id: Q369 - - - name: wikisource - engine: mediawiki - shortcut: ws - categories: general - base_url: "https://{language}.wikisource.org/" - number_of_results: 5 - search_type: text - disabled: true - about: - website: https://www.wikisource.org/ - wikidata_id: Q263 - - - name: wiktionary - engine: mediawiki - shortcut: wt - categories: [dictionaries] - base_url: "https://{language}.wiktionary.org/" - number_of_results: 5 - search_type: text - disabled: false - about: - website: https://www.wiktionary.org/ - wikidata_id: Q151 - - - name: wikiversity - engine: mediawiki - shortcut: wv - categories: general - base_url: "https://{language}.wikiversity.org/" - number_of_results: 5 - search_type: text - disabled: true - about: - website: https://www.wikiversity.org/ - wikidata_id: Q370 - - - name: wikivoyage - engine: mediawiki - shortcut: wy - categories: general - base_url: "https://{language}.wikivoyage.org/" - number_of_results: 5 - search_type: text - disabled: true - about: - website: https://www.wikivoyage.org/ - wikidata_id: Q373 - - - name: wolframalpha - shortcut: wa - # You can use the engine using the official stable API, but you need an API - # key. See: https://products.wolframalpha.com/api/ - # - # engine: wolframalpha_api - # api_key: '' - # - # Or you can use the html non-stable engine, activated by default - engine: wolframalpha_noapi - timeout: 6.0 - categories: [] - - - name: dictzone - engine: dictzone - shortcut: dc - - - name: mymemory translated - engine: translated - shortcut: tl - timeout: 5.0 - disabled: false - # You can use without an API key, but you are limited to 1000 words/day - # See: https://mymemory.translated.net/doc/usagelimits.php - # api_key: '' - - # Required dependency: mysql-connector-python - # - name: mysql - # engine: mysql_server - # database: mydatabase - # username: user - # password: pass - # limit: 10 - # query_str: 'SELECT * from mytable WHERE fieldname=%(query)s' - # shortcut: mysql - - - name: 1337x - engine: 1337x - shortcut: 1337x - disabled: true - - - name: duden - engine: duden - shortcut: du - disabled: true - - - name: seznam - shortcut: szn - engine: seznam - disabled: true - - # - name: deepl - # engine: deepl - # shortcut: dpl - # # You can use the engine using the official stable API, but you need an API key - # # See: https://www.deepl.com/pro-api?cta=header-pro-api - # api_key: '' # required! - # timeout: 5.0 - # disabled: true - - - name: mojeek - shortcut: mjk - engine: xpath - paging: true - categories: [general, web] - search_url: https://www.mojeek.com/search?q={query}&s={pageno}&lang={lang}&lb={lang} - results_xpath: //ul[@class="results-standard"]/li/a[@class="ob"] - url_xpath: ./@href - title_xpath: ../h2/a - content_xpath: ..//p[@class="s"] - suggestion_xpath: //div[@class="top-info"]/p[@class="top-info spell"]/em/a - first_page_num: 0 - page_size: 10 - disabled: true - about: - website: https://www.mojeek.com/ - wikidata_id: Q60747299 - official_api_documentation: https://www.mojeek.com/services/api.html/ - use_official_api: false - require_api_key: false - results: HTML - - - name: naver - shortcut: nvr - categories: [general, web] - engine: xpath - paging: true - search_url: https://search.naver.com/search.naver?where=webkr&sm=osp_hty&ie=UTF-8&query={query}&start={pageno} - url_xpath: //a[@class="link_tit"]/@href - title_xpath: //a[@class="link_tit"] - content_xpath: //a[@class="total_dsc"]/div - first_page_num: 1 - page_size: 10 - disabled: true - about: - website: https://www.naver.com/ - wikidata_id: Q485639 - official_api_documentation: https://developers.naver.com/docs/nmt/examples/ - use_official_api: false - require_api_key: false - results: HTML - language: ko - - - name: rubygems - shortcut: rbg - engine: xpath - paging: true - search_url: https://rubygems.org/search?page={pageno}&query={query} - results_xpath: /html/body/main/div/a[@class="gems__gem"] - url_xpath: ./@href - title_xpath: ./span/h2 - content_xpath: ./span/p - suggestion_xpath: /html/body/main/div/div[@class="search__suggestions"]/p/a - first_page_num: 1 - categories: [it, packages] - disabled: true - about: - website: https://rubygems.org/ - wikidata_id: Q1853420 - official_api_documentation: https://guides.rubygems.org/rubygems-org-api/ - use_official_api: false - require_api_key: false - results: HTML - - - name: peertube - engine: peertube - shortcut: ptb - paging: true - # https://instances.joinpeertube.org/instances - base_url: https://peertube.biz/ - # base_url: https://tube.tardis.world/ - categories: videos - disabled: true - timeout: 6.0 - - - name: mediathekviewweb - engine: mediathekviewweb - shortcut: mvw - disabled: true - - # - name: yacy - # engine: yacy - # shortcut: ya - # base_url: http://localhost:8090 - # required if you aren't using HTTPS for your local yacy instance' - # enable_http: true - # number_of_results: 5 - # timeout: 3.0 - - - name: rumble - engine: rumble - shortcut: ru - base_url: https://rumble.com/ - paging: true - categories: videos - disabled: true - - - name: wordnik - engine: wordnik - shortcut: def - base_url: https://www.wordnik.com/ - categories: [dictionaries] - timeout: 5.0 - disabled: false - - - name: woxikon.de synonyme - engine: xpath - shortcut: woxi - categories: [dictionaries] - timeout: 5.0 - disabled: true - search_url: https://synonyme.woxikon.de/synonyme/{query}.php - url_xpath: //div[@class="upper-synonyms"]/a/@href - content_xpath: //div[@class="synonyms-list-group"] - title_xpath: //div[@class="upper-synonyms"]/a - no_result_for_http_status: [404] - about: - website: https://www.woxikon.de/ - wikidata_id: # No Wikidata ID - use_official_api: false - require_api_key: false - results: HTML - language: de - - - name: sjp.pwn - engine: sjp - shortcut: sjp - base_url: https://sjp.pwn.pl/ - timeout: 5.0 - disabled: true - - # wikimini: online encyclopedia for children - # The fulltext and title parameter is necessary for Wikimini because - # sometimes it will not show the results and redirect instead - - name: wikimini - engine: xpath - shortcut: wkmn - search_url: https://fr.wikimini.org/w/index.php?search={query}&title=Sp%C3%A9cial%3ASearch&fulltext=Search - url_xpath: //li/div[@class="mw-search-result-heading"]/a/@href - title_xpath: //li//div[@class="mw-search-result-heading"]/a - content_xpath: //li/div[@class="searchresult"] - categories: general - disabled: true - about: - website: https://wikimini.org/ - wikidata_id: Q3568032 - use_official_api: false - require_api_key: false - results: HTML - language: fr - - - name: wttr.in - engine: wttr - shortcut: wttr - timeout: 9.0 - - - name: brave - shortcut: brave - engine: xpath - paging: true - time_range_support: true - first_page_num: 0 - time_range_url: "&tf={time_range_val}" - search_url: https://search.brave.com/search?q={query}&offset={pageno}&spellcheck=1{time_range} - url_xpath: //a[@class="result-header"]/@href - title_xpath: //span[@class="snippet-title"] - content_xpath: //p[1][@class="snippet-description"] - suggestion_xpath: //div[@class="text-gray h6"]/a - time_range_map: - day: 'pd' - week: 'pw' - month: 'pm' - year: 'py' - categories: [general, web] - disabled: true - headers: - Accept-Encoding: gzip, deflate - about: - website: https://brave.com/search/ - wikidata_id: Q107355971 - use_official_api: false - require_api_key: false - results: HTML - - - name: petalsearch - shortcut: pts - engine: xpath - paging: true - search_url: https://petalsearch.com/search?query={query}&pn={pageno} - results_xpath: //div[@class="webpage-content"]/div[@class="title-cont"]/a - url_xpath: ./@href - title_xpath: . - content_xpath: ../../div[@class="webpage-text"] - suggestion_xpath: //div[@class="related-search-items"]/a - first_page_num: 1 - disabled: true - about: - website: https://petalsearch.com/ - wikidata_id: Q104399280 - use_official_api: false - require_api_key: false - results: HTML - - - name: petalsearch images - engine: petal_images - shortcut: ptsi - disabled: true - timeout: 3.0 - - - name: petalsearch news - shortcut: ptsn - categories: news - engine: xpath - paging: true - search_url: https://petalsearch.com/search?channel=news&query={query}&pn={pageno} - results_xpath: //div[@class="news-container"]/div/div/div/a - url_xpath: ./@href - title_xpath: ./div - content_xpath: ../div[@class="news-text"] - thumbnail_xpath: ../../../../img/@src - first_page_num: 1 - disabled: true - about: - website: https://petalsearch.com/ - wikidata_id: Q104399280 - use_official_api: false - require_api_key: false - results: HTML - - - name: lib.rs - shortcut: lrs - engine: xpath - search_url: https://lib.rs/search?q={query} - results_xpath: /html/body/main/div/ol/li/a - url_xpath: ./@href - title_xpath: ./div[@class="h"]/h4 - content_xpath: ./div[@class="h"]/p - categories: [it, packages] - disabled: true - about: - website: https://lib.rs - wikidata_id: Q113486010 - use_official_api: false - require_api_key: false - results: HTML - - - name: sourcehut - shortcut: srht - engine: xpath - paging: true - search_url: https://sr.ht/projects?page={pageno}&search={query} - results_xpath: (//div[@class="event-list"])[1]/div[@class="event"] - url_xpath: ./h4/a[2]/@href - title_xpath: ./h4/a[2] - content_xpath: ./p - first_page_num: 1 - categories: [it, repos] - disabled: true - about: - website: https://sr.ht - wikidata_id: Q78514485 - official_api_documentation: https://man.sr.ht/ - use_official_api: false - require_api_key: false - results: HTML - - - name: goo - shortcut: goo - engine: xpath - paging: true - search_url: https://search.goo.ne.jp/web.jsp?MT={query}&FR={pageno}0 - url_xpath: //div[@class="result"]/p[@class='title fsL1']/a/@href - title_xpath: //div[@class="result"]/p[@class='title fsL1']/a - content_xpath: //p[contains(@class,'url fsM')]/following-sibling::p - first_page_num: 0 - categories: [general, web] - disabled: true - timeout: 4.0 - about: - website: https://search.goo.ne.jp - wikidata_id: Q249044 - use_official_api: false - require_api_key: false - results: HTML - language: ja - -# Doku engine lets you access to any Doku wiki instance: -# A public one or a privete/corporate one. -# - name: ubuntuwiki -# engine: doku -# shortcut: uw -# base_url: 'https://doc.ubuntu-fr.org' - -# Be careful when enabling this engine if you are -# running a public instance. Do not expose any sensitive -# information. You can restrict access by configuring a list -# of access tokens under tokens. -# - name: git grep -# engine: command -# command: ['git', 'grep', '{{QUERY}}'] -# shortcut: gg -# tokens: [] -# disabled: true -# delimiter: -# chars: ':' -# keys: ['filepath', 'code'] - -# Be careful when enabling this engine if you are -# running a public instance. Do not expose any sensitive -# information. You can restrict access by configuring a list -# of access tokens under tokens. -# - name: locate -# engine: command -# command: ['locate', '{{QUERY}}'] -# shortcut: loc -# tokens: [] -# disabled: true -# delimiter: -# chars: ' ' -# keys: ['line'] - -# Be careful when enabling this engine if you are -# running a public instance. Do not expose any sensitive -# information. You can restrict access by configuring a list -# of access tokens under tokens. -# - name: find -# engine: command -# command: ['find', '.', '-name', '{{QUERY}}'] -# query_type: path -# shortcut: fnd -# tokens: [] -# disabled: true -# delimiter: -# chars: ' ' -# keys: ['line'] - -# Be careful when enabling this engine if you are -# running a public instance. Do not expose any sensitive -# information. You can restrict access by configuring a list -# of access tokens under tokens. -# - name: pattern search in files -# engine: command -# command: ['fgrep', '{{QUERY}}'] -# shortcut: fgr -# tokens: [] -# disabled: true -# delimiter: -# chars: ' ' -# keys: ['line'] - -# Be careful when enabling this engine if you are -# running a public instance. Do not expose any sensitive -# information. You can restrict access by configuring a list -# of access tokens under tokens. -# - name: regex search in files -# engine: command -# command: ['grep', '{{QUERY}}'] -# shortcut: gr -# tokens: [] -# disabled: true -# delimiter: -# chars: ' ' -# keys: ['line'] - -doi_resolvers: - oadoi.org: 'https://oadoi.org/' - doi.org: 'https://doi.org/' - doai.io: 'https://dissem.in/' - sci-hub.se: 'https://sci-hub.se/' - sci-hub.st: 'https://sci-hub.st/' - sci-hub.ru: 'https://sci-hub.ru/' - -default_doi_resolver: 'oadoi.org' diff --git a/conf/uwsgi.ini b/conf/uwsgi.ini index 6dfe023..d4cfa45 100644 --- a/conf/uwsgi.ini +++ b/conf/uwsgi.ini @@ -1,37 +1,70 @@ +# -*- mode: conf; coding: utf-8 -*- [uwsgi] -# Who will run the code + +# uWSGI core +# ---------- +# +# https://uwsgi-docs.readthedocs.io/en/latest/Options.html#uwsgi-core + +# Who will run the code / Hint: in emperor-tyrant mode uid & gid setting will be +# ignored [1]. Mode emperor-tyrant is the default on fedora (/etc/uwsgi.ini). +# +# [1] https://uwsgi-docs.readthedocs.io/en/latest/Emperor.html#tyrant-mode-secure-multi-user-hosting +# uid = __APP__ gid = __APP__ -# Number of workers -workers = 4 +# set (python) default encoding UTF-8 +env = LANG=C.UTF-8 +env = LANGUAGE=C.UTF-8 +env = LC_ALL=C.UTF-8 + +# chdir to specified directory before apps loading +chdir = __INSTALL_DIR__/searxng-src/searx + +# SearXNG configuration (settings.yml) +env = SEARXNG_SETTINGS_PATH=__INSTALL_DIR__/settings.yml + +# disable logging for privacy +disable-logging = true # The right granted on the created socket chmod-socket = 666 -# Plugin to use and interpretor config +# Plugin to use and interpreter config single-interpreter = true + +# enable master process master = true -plugin = python3,http + +# load apps in each worker instead of the master lazy-apps = true + +# load uWSGI plugins +plugin = python3,http + +# By default the Python plugin does not initialize the GIL. This means your +# app-generated threads will not run. If you need threads, remember to enable +# them with enable-threads. Running uWSGI in multithreading mode (with the +# threads options) will automatically enable threading support. This *strange* +# default behaviour is for performance reasons. enable-threads = true -# Application base folder -base = __FINALPATH__ -# Support running the module from a webserver subdirectory. -route-run = fixpathinfo: +# plugin: python +# -------------- +# +# https://uwsgi-docs.readthedocs.io/en/latest/Options.html#plugin-python -# Module to import +# load a WSGI module module = searx.webapp -# Virtualenv and python path -virtualenv = __FINALPATH__/venv/ -pythonpath = __FINALPATH__ -chdir = __FINALPATH__/searx/ +# set PYTHONHOME/virtualenv +virtualenv = __INSTALL_DIR__/searxng-pyenv + +# add directory (or glob) to pythonpath +pythonpath = __INSTALL_DIR__ -# The variable holding flask application -callable = app # speak to upstream # ----------------- @@ -44,11 +77,8 @@ buffer-size = 8192 # ui: # static_use_hash: true # -static-map = /static=__FINALPATH__/searx/static +static-map = /static=__INSTALL_DIR__/searxng-src/searx/static # expires set to one year since there are hashes static-expires = /* 31557600 static-gzip-all = True offload-threads = %k - -# Cache -cache2 = name=searxngcache,items=2000,blocks=2000,blocksize=4096,bitmap=1 diff --git a/config_panel.toml.example b/config_panel.toml.example deleted file mode 100644 index c6bccd8..0000000 --- a/config_panel.toml.example +++ /dev/null @@ -1,295 +0,0 @@ - -## Config panel are available from webadmin > Apps > YOUR_APP > Config Panel Button -## Those panels let user configure some params on their apps using a friendly interface, -## and remove the need to manually edit files from the command line. - -## From a packager perspective, this .toml is coupled to the scripts/config script, -## which may be used to define custom getters/setters. However, most use cases -## should be covered automagically by the core, thus it may not be necessary -## to define a scripts/config at all! - -## ----------------------------------------------------------------------------- -## IMPORTANT: In accordance with YunoHost's spirit, please keep things simple and -## do not overwhelm the admin with tons of misunderstandable or advanced settings. -## ----------------------------------------------------------------------------- - -## The top level describe the entire config panels screen. - -## The version is a required property. -## Here a small reminder to associate config panel version with YunoHost version -## | Config | YNH | Config panel small change log | -## | ------ | --- | ------------------------------------------------------- | -## | 0.1 | 3.x | 0.1 config script not compatible with YNH >= 4.3 | -## | 1.0 | 4.3.x | The new config panel system with 'bind' property | -version = "1.0" - -## (optional) i18n property let you internationalize questions, however this feature -## is only available in core configuration panel (like yunohost domain config). -## So in app config panel this key is ignored for now, but you can internationalize -## by using a lang dictionary (see property name bellow) -# i18n = "prefix_translation_key" - -################################################################################ -#### ABOUT PANELS -################################################################################ - -## The next level describes web admin panels -## You have to choose an ID for each panel, in this example the ID is "main" -## Keep in mind this ID will be used in CLI to refer to your question, so choose -## something short and meaningfull. -## In the webadmin, each panel corresponds to a distinct tab / form -[main] - -## Define the label for your panel -## Internationalization works similarly to the 'description' and 'ask' questions in the manifest -# name.en = "Main configuration" -# name.fr = "Configuration principale" - -## (optional) If you need to trigger a service reload-or-restart after the user -## change a question in this panel, you can add your service in the list. -services = ["__APP__"] -# or services = ["nginx", "__APP__"] to also reload-or-restart nginx - -## (optional) This help properties is a short help displayed on the same line -## than the panel title but not displayed in the tab. -# help = "" - - ############################################################################ - #### ABOUT SECTIONS - ############################################################################ - - ## A panel is composed of one or several sections. - ## - ## Sections are meant to group questions together when they correspond to - ## a same subtopic. This impacts the rendering in terms of CLI prompts - ## and HTML forms - ## - ## You should choose an ID for your section, and prefix it with the panel ID - ## (Be sure to not make a typo in the panel ID, which would implicitly create - ## an other entire panel) - ## - ## We use the context of pepettes_ynh as an example, - ## which is a simple donation form app written in python, - ## and for which the admin will want to edit the configuration - [main.customization] - - ## (optional) Defining a proper title for sections is not mandatory - ## and depends on the exact rendering you're aiming for the CLI / webadmin - name = "" - - ## (optional) This help properties is a short help displayed on the same line - ## than the section title, meant to provide additional details - # help = "" - - ## (optional) As for panel, you can specify to trigger a service - ## reload-or-restart after the user change a question in this section. - ## This property is added to the panel property, it doesn't deactivate it. - ## So no need to replicate, the service list from panel services property. - # services = [] - - ## (optional) By default all questions are optionals, but you can specify a - ## default behaviour for question in the section - optional = false - - ## (optional) It's also possible with the 'visible' property to only - ## display the section depending on the user's answers to previous questions. - ## - ## Be careful that the 'visible' property should only refer to **previous** questions - ## Hence, it should not make sense to have a "visible" property on the very first section. - ## - ## Also, keep in mind that this feature only works in the webadmin and not in CLI - ## (therefore a user could be prompted in CLI for a question that may not be relevant) - # visible = true - - ######################################################################## - #### ABOUT QUESTIONS - ######################################################################## - - ## A section is compound of one or several questions. - - ## --------------------------------------------------------------------- - ## IMPORTANT: as for panel and section you have to choose an ID, but this - ## one should be unique in all this document, even if the question is in - ## an other panel. - ## --------------------------------------------------------------------- - - ## You can use same questions types and properties than in manifest.yml - ## install part. However, in YNH 4.3, a lot of change has been made to - ## extend availables questions types list. - ## See: TODO DOC LINK - - [main.customization.project_name] - - ## (required) The ask property is equivalent to the ask property in - ## the manifest. However, in config panels, questions are displayed on the - ## left side and therefore have less space to be rendered. Therefore, - ## it is better to use a short question, and use the "help" property to - ## provide additional details if necessary. - ask.en = "Name of the project" - - ## (required) The type property indicates how the question should be - ## displayed, validated and managed. Some types have specific properties. - ## - ## Types available: string, boolean, number, range, text, password, path - ## email, url, date, time, color, select, domain, user, tags, file. - ## - ## For a complete list with specific properties, see: TODO DOC LINK - type = "string" - - ######################################################################## - #### ABOUT THE BIND PROPERTY - ######################################################################## - - ## (recommended) 'bind' property is a powerful feature that let you - ## configure how and where the data will be read, validated and written. - - ## By default, 'bind property is in "settings" mode, it means it will - ## **only** read and write the value in application settings file. - ## bind = "settings" - - ## However, settings usually correspond to key/values in actual app configurations - ## Hence, a more useful mode is to have bind = ":FILENAME". In that case, YunoHost - ## will automagically find a line with "KEY=VALUE" in FILENAME - ## (with the adequate separator between KEY and VALUE) - ## - ## YunoHost will then use this value for the read/get operation. - ## During write/set operations, YunoHost will overwrite the value - ## in **both** FILENAME and in the app's settings.yml - - ## Configuration file format supported: yaml, toml, json, ini, env, php, - ## python. The feature probably works with others formats, but should be tested carefully. - - ## Note that this feature only works with relatively simple cases - ## such as `KEY: VALUE`, but won't properly work with - ## complex data structures like multilin array/lists or dictionnaries. - ## It also doesn't work with XML format, custom config function call, php define(), ... - - ## More info on TODO - # bind = ":/var/www/__APP__/settings.py" - - - ## By default, bind = ":FILENAME" will use the question ID as KEY - ## ... but the question ID may sometime not be the exact KEY name in the configuration file. - ## - ## In particular, in pepettes, the python variable is 'name' and not 'project_name' - ## (c.f. https://github.com/YunoHost-Apps/pepettes_ynh/blob/5cc2d3ffd6529cc7356ff93af92dbb6785c3ab9a/conf/settings.py##L11 ) - ## - ## In that case, the key name can be specified before the column ':' - - bind = "name:/var/www/__APP__/settings.py" - - ## --------------------------------------------------------------------- - ## IMPORTANT: other 'bind' mode exists: - ## - ## bind = "FILENAME" (with no column character before FILENAME) - ## may be used to bind to the **entire file content** (instead of a single KEY/VALUE) - ## This could be used to expose an entire configuration file, or binary files such as images - ## For example: - ## bind = "/var/www/__APP__/img/logo.png" - ## - ## bind = "null" can be used to disable reading / writing in settings. - ## This creates sort of a "virtual" or "ephemeral" question which is not related to any actual setting - ## In this mode, you are expected to define custom getter/setters/validators in scripts/config: - ## - ## getter: get__QUESTIONID() - ## setter: set__QUESTIONID() - ## validator: validate__QUESTIONID() - ## - ## You can also specify a common getter / setter / validator, with the - ## function 'bind' mode, for example here it will try to run - ## get__array_settings() first. - # bind = "array_settings()" - ## --------------------------------------------------------------------- - - ## --------------------------------------------------------------------- - ## IMPORTANT: with the exception of bind=null questions, - ## question IDs should almost **always** correspond to an app setting - ## initialized / reused during install/upgrade. - ## Not doing so may result in inconsistencies between the config panel mechanism - ## and the use of ynh_add_config - ## --------------------------------------------------------------------- - - ######################################################################## - #### OTHER GENERIC PROPERTY FOR QUESTIONS - ######################################################################## - - ## (optional) An help text for the question - help = "Fill the name of the project which will received donation" - - ## (optional) An example display as placeholder in web form - # example = "YunoHost" - - ## (optional) set to true in order to redact the value in operation logs - # redact = false - - ## (optional) A validation pattern - ## --------------------------------------------------------------------- - ## IMPORTANT: your pattern should be between simple quote, not double. - ## --------------------------------------------------------------------- - pattern.regexp = '^\w{3,30}$' - pattern.error = "The name should be at least 3 chars and less than 30 chars. Alphanumeric chars are accepted" - - ## Note: visible and optional properties are also available for questions - - - [main.customization.contact_url] - ask = "Contact url" - type = "url" - example = "mailto: contact@example.org" - help = "mailto: accepted" - pattern.regexp = '^mailto:[^@]+@[^@]+|https://$' - pattern.error = "Should be https or mailto:" - bind = ":/var/www/__APP__/settings.py" - - [main.customization.logo] - ask = "Logo" - type = "file" - accept = ".png" - help = "Fill with an already resized logo" - bind = "__FINALPATH__/img/logo.png" - - [main.customization.favicon] - ask = "Favicon" - type = "file" - accept = ".png" - help = "Fill with an already sized favicon" - bind = "__FINALPATH__/img/favicon.png" - - - [main.stripe] - name = "Stripe general info" - optional = false - - # The next alert is overwrited with a getter from the config script - [main.stripe.amount] - ask = "Donation in the month : XX € - type = "alert" - style = "success" - - [main.stripe.publishable_key] - ask = "Publishable key" - type = "string" - redact = true - help = "Indicate here the stripe publishable key" - bind = ":/var/www/__APP__/settings.py" - - [main.stripe.secret_key] - ask = "Secret key" - type = "string" - redact = true - help = "Indicate here the stripe secret key" - bind = ":/var/www/__APP__/settings.py" - - [main.stripe.prices] - ask = "Prices ID" - type = "tags" - help = """\ - Indicates here the prices ID of donation products you created in stripe interfaces. \ - Go on [Stripe products](https://dashboard.stripe.com/products) to create those donation products. \ - Fill it tag with 'FREQUENCY/CURRENCY/PRICE_ID' \ - FREQUENCY: 'one_time' or 'recuring' \ - CURRENCY: 'EUR' or 'USD' \ - PRICE_ID: ID from stripe interfaces starting with 'price_' \ - """ - pattern.regexp = '^(one_time|recuring)/(EUR|USD)/price_.*$' - pattern.error = "Please respect the format describe in help text for each price ID" diff --git a/doc/DISCLAIMER.md b/doc/ADMIN.md similarity index 52% rename from doc/DISCLAIMER.md rename to doc/ADMIN.md index 3677b6f..06f4bd3 100644 --- a/doc/DISCLAIMER.md +++ b/doc/ADMIN.md @@ -1 +1,5 @@ +The app install dir is `__INSTALL_DIR__`. +Don't edit settings in that directory. +Instead edit them in `__INSTALL_DIR__/settings.conf`. That file overwrite the default settings thanks to `use_default_settings: true` + Please note that this application is a rolling-release (i.e. each commit is a release) and thus is updated very regularly. People not updating frequently may encounter some bugs or disruptions due to the very nature of this software. diff --git a/manifest.json b/manifest.json deleted file mode 100644 index 020c59b..0000000 --- a/manifest.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "name": "SearXNG", - "id": "searxng", - "packaging_format": 1, - "description": { - "en": "A free internet metasearch engine which aggregates results from more than 70 search services. Users are neither tracked nor profiled", - "fr": "Un méta-moteur de recherche qui rassemble les résultats de plus de 70 services de recherche. Les utilisateurs ne sont ni suivis ni espionnés" - }, - "version": "2023.08.30.14.25.41~ynh1", - "url": "https://docs.searxng.org/", - "upstream": { - "license": "AGPL-3.0-or-later", - "website": "https://docs.searxng.org/", - "demo": "https://searx.be/", - "admindoc": "https://docs.searxng.org/admin/", - "userdoc": "https://docs.searxng.org/user/", - "code": "https://github.com/searxng/searxng" - }, - "license": "AGPL-3.0-or-later", - "maintainer": { - "name": "mh4ckt3mh4ckt1c4s", - "email": "mh4ckt3mh4ckt1c4s@protonmail.com" - }, - "requirements": { - "yunohost": ">= 11.0.0" - }, - "multi_instance": false, - "services": [ - "nginx" - ], - "arguments": { - "install": [ - { - "name": "domain", - "type": "domain" - }, - { - "name": "path", - "type": "path", - "example": "/searxng", - "default": "/searxng" - }, - { - "name": "is_public", - "type": "boolean", - "default": true - }, - { - "name": "admin", - "type": "user" - } - ] - } -} diff --git a/manifest.toml b/manifest.toml new file mode 100644 index 0000000..bc416db --- /dev/null +++ b/manifest.toml @@ -0,0 +1,52 @@ +packaging_format = 2 + +id = "searxng" +name = "SearXNG" +description.en = "A free internet metasearch engine which aggregates results from more than 70 search services. Users are neither tracked nor profiled" +description.fr = "Un méta-moteur de recherche qui rassemble les résultats de plus de 70 services de recherche. Les utilisateurs ne sont ni suivis ni espionnés" + +version = "2023.09.18.10.00.00~ynh1" + +maintainers = ["mh4ckt3mh4ckt1c4s"] + +[upstream] +license = "AGPL-3.0-or-later" +website = "https://docs.searxng.org" +demo = "https://searx.be" +admindoc = "https://docs.searxng.org/admin/" +userdoc = "https://docs.searxng.org/user/" +code = "https://github.com/searxng/searxng" + +[integration] +yunohost = ">= 11.1.0" +architectures = "all" +multi_instance = false +ldap = "not_relevant" +sso = "not_relevant" +disk = "210M" +ram.build = "250M" +ram.runtime = "200M" + +[install] + [install.domain] + type = "domain" + + [install.path] + type = "path" + default = "/searxng" + + [install.init_main_permission] + type = "group" + default = "visitors" + +[resources] + [resources.system_user] + + [resources.install_dir] + dir = "/var/www/__APP__" + + [resources.permissions] + main.url = "/" + + [resources.apt] + packages = "git, build-essential, libxslt-dev, python3-dev, python3-venv, python3-cffi, python3-babel, zlib1g-dev, libffi-dev, libssl-dev, python3-lxml, uwsgi, uwsgi-plugin-python3, shellcheck" diff --git a/scripts/_common.sh b/scripts/_common.sh index 92838dd..c92b945 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -4,8 +4,8 @@ # COMMON VARIABLES #================================================= -# dependencies used by the app -pkg_dependencies="git build-essential libxslt-dev python3-dev python3-venv python3-cffi python3-babel zlib1g-dev libffi-dev libssl-dev python3-lxml uwsgi uwsgi-plugin-python3 shellcheck" +repo_fullpath="https://github.com/searxng/searxng" +commit_sha="a9b6963971327605db1509795be7795dc7401f3f" #================================================= # UWSGI HELPERS @@ -15,9 +15,9 @@ pkg_dependencies="git build-essential libxslt-dev python3-dev python3-venv pytho # # usage: ynh_check_global_uwsgi_config ynh_check_global_uwsgi_config () { - uwsgi --version || ynh_die --message "You need to add uwsgi (and appropriate plugin) as a dependency" + uwsgi --version || ynh_die --message="You need to add uwsgi (and appropriate plugin) as a dependency" - cat > /etc/systemd/system/uwsgi-app@.service < "/etc/systemd/system/uwsgi-app@.service" < uwsgi-app@app` ynh_add_uwsgi_service () { - ynh_check_global_uwsgi_config + ynh_check_global_uwsgi_config - local others_var=${1:-} - local finaluwsgiini="/etc/uwsgi/apps-available/$app.ini" + local finaluwsgiini="/etc/uwsgi/apps-available/$app.ini" - # www-data group is needed since it is this nginx who will start the service - usermod --append --groups www-data "$app" || ynh_die --message "It wasn't possible to add user $app to group www-data" + # www-data group is needed since it is this nginx who will start the service + usermod --append --groups www-data "$app" || ynh_die --message="It wasn't possible to add user $app to group www-data" - ynh_backup_if_checksum_is_different "$finaluwsgiini" - cp ../conf/uwsgi.ini "$finaluwsgiini" + ynh_add_config --template="uwsgi.ini" --destination="$finaluwsgiini" + ynh_store_file_checksum --file="$finaluwsgiini" + chown $app:root "$finaluwsgiini" - # 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 --match_string "__FINALPATH__" --replace_string "$final_path" --target_file "$finaluwsgiini" - fi - if test -n "${path_url:-}"; then - ynh_replace_string --match_string "__PATH__" --replace_string "$path_url" --target_file "$finaluwsgiini" - fi - if test -n "${app:-}"; then - ynh_replace_string --match_string "__APP__" --replace_string "$app" --target_file "$finaluwsgiini" - fi + # make sure the folder for logs exists and set authorizations + mkdir -p "/var/log/uwsgi/$app" + chown $app:root "/var/log/uwsgi/$app" + chmod -R u=rwX,g=rX,o= "/var/log/uwsgi/$app" - # Replace all other variable given as arguments - for var_to_replace in $others_var - do - # ${var_to_replace^^} make the content of the variable on upper-cases - # ${!var_to_replace} get the content of the variable named $var_to_replace - ynh_replace_string --match_string "__${var_to_replace^^}__" --replace_string "${!var_to_replace}" --target_file "$finaluwsgiini" - done + # Setup specific Systemd rules if necessary + mkdir -p "/etc/systemd/system/uwsgi-app@$app.service.d" + if [ -e "../conf/uwsgi-app@override.service" ]; then + ynh_add_config --template="uwsgi-app@override.service" --destination="/etc/systemd/system/uwsgi-app@$app.service.d/override.conf" + fi - ynh_store_file_checksum --file "$finaluwsgiini" + systemctl daemon-reload + ynh_systemd_action --service_name="uwsgi-app@$app.service" --action="enable" - chown $app:root "$finaluwsgiini" - - # make sure the folder for logs exists and set authorizations - mkdir -p /var/log/uwsgi/$app - chown $app:root /var/log/uwsgi/$app - chmod -R u=rwX,g=rX,o= /var/log/uwsgi/$app - - # Setup specific Systemd rules if necessary - test -e ../conf/uwsgi-app@override.service && \ - mkdir /etc/systemd/system/uwsgi-app@$app.service.d && \ - cp ../conf/uwsgi-app@override.service /etc/systemd/system/uwsgi-app@$app.service.d/override.conf - - systemctl daemon-reload - systemctl enable "uwsgi-app@$app.service" --quiet - - # Add as a service - yunohost service add "uwsgi-app@$app" --log "/var/log/uwsgi/$app/$app.log" + # Add as a service + yunohost service add "uwsgi-app@$app" --description="uWSGI service for searxng" --log "/var/log/uwsgi/$app/$app.log" } # Remove the dedicated uwsgi ini file # # usage: ynh_remove_uwsgi_service ynh_remove_uwsgi_service () { - local finaluwsgiini="/etc/uwsgi/apps-available/$app.ini" - if [ -e "$finaluwsgiini" ]; then - yunohost service remove "uwsgi-app@$app" - systemctl disable "uwsgi-app@$app.service" --quiet + local finaluwsgiini="/etc/uwsgi/apps-available/$app.ini" + if [ -e "$finaluwsgiini" ]; then + yunohost service remove "uwsgi-app@$app" + ynh_systemd_action --service_name="uwsgi-app@$app.service" --action="stop" + ynh_exec_fully_quiet ynh_systemd_action --service_name="uwsgi-app@$app.service" --action="disable" - ynh_secure_remove --file="$finaluwsgiini" - ynh_secure_remove --file="/var/log/uwsgi/$app" - ynh_secure_remove --file="/etc/systemd/system/uwsgi-app@$app.service.d" - fi - if [ -e /etc/init.d/uwsgi ] - then - # Redémarre le service uwsgi si il n'est pas désinstallé. - ynh_systemd_action --service_name=uwsgi --action=start - else - if yunohost service status | grep -q uwsgi - then - ynh_print_info --message="Remove uwsgi service" - yunohost service remove uwsgi - fi - fi + ynh_secure_remove --file="$finaluwsgiini" + ynh_secure_remove --file="/var/log/uwsgi/$app" + ynh_secure_remove --file="/etc/systemd/system/uwsgi-app@$app.service.d" + fi } - -#================================================= - -# Remove a file or a directory securely +# Backup the dedicated uwsgi config +# Should be used in backup script # -# usage: ynh_regex_secure_remove --file=path_to_remove [--regex=regex to append to $file] [--non_recursive] [--dry_run] -# | arg: -f, --file - File or directory to remove -# | arg: -r, --regex - Regex to append to $file to filter the files to remove -# | arg: -n, --non_recursive - Perform a non recursive rm and a non recursive search with the regex -# | arg: -d, --dry_run - Do not remove, only list the files to remove -# -# Requires YunoHost version 2.6.4 or higher. -ynh_regex_secure_remove () { - # Declare an array to define the options of this helper. - local legacy_args=frnd - declare -Ar args_array=( [f]=file= [r]=regex= [n]=non_recursive [d]=dry_run ) - local file - local regex - local dry_run - local non_recursive - # Manage arguments with getopts - ynh_handle_getopts_args "$@" - regex=${regex:-} - dry_run=${dry_run:-0} - non_recursive=${non_recursive:-0} - - local forbidden_path=" -/var/www \ -/home/yunohost.app" - - # Fail if no argument is provided to the helper. - if [ -z "$file" ] - then - ynh_print_warn --message="ynh_regex_secure_remove called with no argument --file, ignoring." - return 0 - fi - - if [ -n "$regex" ] - then - if [ -e "$file" ] - then - if [ $non_recursive -eq 1 ]; then - local recursive="-maxdepth 1" - else - local recursive="" - fi - # Use find to list the files in $file and grep to filter with the regex - files_to_remove="$(find -P "$file" $recursive -name ".." -prune -o -print | grep --extended-regexp "$regex")" - else - ynh_print_info --message="'$file' wasn't deleted because it doesn't exist." - return 0 - fi - else - files_to_remove="$file" - fi - - # Check each file before removing it - while read file_to_remove - do - if [ -n "$file_to_remove" ] - then - # Check all forbidden path before removing anything - # First match all paths or subpaths in $forbidden_path - if [[ "$forbidden_path" =~ "$file_to_remove" ]] || \ - # Match all first level paths from / (Like /var, /root, etc...) - [[ "$file_to_remove" =~ ^/[[:alnum:]]+$ ]] || \ - # Match if the path finishes by /. Because it seems there is an empty variable - [ "${file_to_remove:${#file_to_remove}-1}" = "/" ] - then - ynh_print_err --message="Not deleting '$file_to_remove' because this path is forbidden !!!" - - # If the file to remove exists - elif [ -e "$file_to_remove" ] - then - if [ $dry_run -eq 1 ] - then - ynh_print_warn --message="File to remove: $file_to_remove" - else - if [ $non_recursive -eq 1 ]; then - local recursive="" - else - local recursive="--recursive" - fi - - # Remove a file or a directory - rm --force $recursive "$file_to_remove" - fi - else - # Ignore non existent files with regex, as we likely remove the parent directory before its content is listed. - if [ -z "$regex" ] - then - ynh_print_info --message="'$file_to_remove' wasn't deleted because it doesn't exist." - fi - fi - fi - done <<< "$(echo "$files_to_remove")" +# usage: ynh_backup_uwsgi_service +ynh_backup_uwsgi_service () { + ynh_backup --src_path="/etc/uwsgi/apps-available/$app.ini" + ynh_backup --src_path="/etc/systemd/system/uwsgi-app@$app.service.d" +} + +# Restore the dedicated uwsgi config +# Should be used in restore script +# +# usage: ynh_restore_uwsgi_service +ynh_restore_uwsgi_service () { + ynh_check_global_uwsgi_config + ynh_restore_file --origin_path="/etc/uwsgi/apps-available/$app.ini" + ynh_restore_file --origin_path="/etc/systemd/system/uwsgi-app@$app.service.d" + + mkdir -p "/var/log/uwsgi/$app" + chown $app:root "/var/log/uwsgi/$app" + chmod -R u=rwX,g=rX,o= "/var/log/uwsgi/$app" + + ynh_systemd_action --service_name="uwsgi-app@$app.service" --action="enable" + yunohost service add "uwsgi-app@$app" --description="uWSGI service for searxng" --log "/var/log/uwsgi/$app/$app.log" } diff --git a/scripts/backup b/scripts/backup index ec907d2..a40341f 100755 --- a/scripts/backup +++ b/scripts/backup @@ -6,46 +6,19 @@ # IMPORT GENERIC HELPERS #================================================= -# Keep this path for calling _common.sh inside the execution's context of backup and restore scripts source ../settings/scripts/_common.sh source /usr/share/yunohost/helpers -#================================================= -# MANAGE SCRIPT FAILURE -#================================================= - -ynh_clean_setup () { - ### Remove this function if there's nothing to clean before calling the remove script. - true -} -# Exit if an error occurs during the execution of the script -ynh_abort_if_errors - -#================================================= -# LOAD SETTINGS -#================================================= -ynh_print_info --message="Loading installation settings..." - -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..." -### N.B. : the following 'ynh_backup' calls are only a *declaration* of what needs -### to be backuped and not an actual copy of any file. The actual backup that -### creates and fill the archive with the files happens in the core after this -### script is called. Hence ynh_backups calls takes basically 0 seconds to run. - #================================================= # BACKUP THE APP MAIN DIR #================================================= -ynh_backup --src_path="$final_path" +ynh_backup --src_path="$install_dir" #================================================= # BACKUP THE NGINX CONFIGURATION @@ -59,7 +32,7 @@ ynh_backup --src_path="/etc/nginx/conf.d/$domain.d/$app.conf" # BACKUP UWSGI CONFIG #================================================= -ynh_backup --src_path="/etc/uwsgi/apps-available/$app.ini" +ynh_backup_uwsgi_service #================================================= # END OF SCRIPT diff --git a/scripts/change_url b/scripts/change_url index a7bc00b..4c96bce 100644 --- a/scripts/change_url +++ b/scripts/change_url @@ -9,64 +9,6 @@ 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..." --weight=1 - -# Needed for helper "ynh_add_nginx_config" -final_path=$(ynh_app_setting_get --app=$app --key=final_path) - -# Add settings here as needed by your application -#db_name=$(ynh_app_setting_get --app=$app --key=db_name) -#db_user=$db_name -#db_pwd=$(ynh_app_setting_get --app=$app --key=db_pwd) - -#================================================= -# BACKUP BEFORE CHANGE URL THEN ACTIVE TRAP -#================================================= -ynh_script_progression --message="Backing up the app before changing its URL (may take a while)..." --weight=1 - -# Backup the current version of the app -ynh_backup_before_upgrade -ynh_clean_setup () { - # 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 #================================================= @@ -74,37 +16,14 @@ fi #================================================= ynh_script_progression --message="Stopping a systemd service..." --weight=1 -ynh_systemd_action --service_name="uwsgi-app@$app.service" --action="stop" --log_path="/var/log/$app/$app.log" +ynh_systemd_action --service_name="uwsgi-app@$app.service" --action="stop" --log_path="/var/log/uwsgi/$app/$app.log" #================================================= # MODIFY URL IN NGINX CONF #================================================= ynh_script_progression --message="Updating NGINX web server configuration..." --weight=1 -nginx_conf_path=/etc/nginx/conf.d/$old_domain.d/$app.conf - -# Change the path in the NGINX config file -if [ $change_path -eq 1 ] -then - # Make a backup of the original NGINX config file if modified - ynh_backup_if_checksum_is_different --file="$nginx_conf_path" - # Set global variables for NGINX helper - domain="$old_domain" - path_url="$new_path" - path_no_root=${path_url%/} - # Create a dedicated NGINX config - ynh_add_nginx_config "path_no_root" -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 +ynh_change_url_nginx_config #================================================= # SPECIFIC MODIFICATIONS @@ -113,7 +32,7 @@ fi #================================================= ynh_script_progression --message="Reconfiguring SearXNG..." --weight=2 -ynh_replace_string --match_string="base_url: https://$old_domain$old_path" --replace_string="base_url: https://$new_domain$new_path" --target_file="$final_path/searx/settings.yml" +ynh_replace_string --match_string="base_url: https://$old_domain$old_path" --replace_string="base_url: https://$new_domain$new_path" --target_file="$install_dir/settings.yml" #================================================= # GENERIC FINALISATION @@ -122,14 +41,7 @@ ynh_replace_string --match_string="base_url: https://$old_domain$old_path" --rep #================================================= ynh_script_progression --message="Starting a systemd service..." --weight=1 -ynh_systemd_action --service_name=uwsgi-app@$app.service --action="start" --log_path="/var/log/$app/$app.log" - -#================================================= -# RELOAD NGINX -#================================================= -ynh_script_progression --message="Reloading NGINX web server..." --weight=1 - -ynh_systemd_action --service_name=nginx --action=reload +ynh_systemd_action --service_name="uwsgi-app@$app.service" --action="start" --log_path="/var/log/uwsgi/$app/$app.log" #================================================= # END OF SCRIPT diff --git a/scripts/config b/scripts/config deleted file mode 100644 index b9e79f8..0000000 --- a/scripts/config +++ /dev/null @@ -1,102 +0,0 @@ -#!/bin/bash -# In simple cases, you don't need a config script. - -# With a simple config_panel.toml, you can write in the app settings, in the -# upstream config file or replace complete files (logo ...) and restart services. - -# The config scripts allows you to go further, to handle specific cases -# (validation of several interdependent fields, specific getter/setter for a value, -# display dynamic informations or choices, pre-loading of config type .cube... ). - -#================================================= -# GENERIC STARTING -#================================================= -# IMPORT GENERIC HELPERS -#================================================= - -source /usr/share/yunohost/helpers - -ynh_abort_if_errors - -#================================================= -# RETRIEVE ARGUMENTS -#================================================= - -final_path=$(ynh_app_setting_get $app final_path) - -#================================================= -# SPECIFIC GETTERS FOR TOML SHORT KEY -#================================================= - -get__amount() { - # Here we can imagine to have an API call to stripe to know the amount of donation during a month - local amount = 200 - - # It's possible to change some properties of the question by overriding it: - if [ $amount -gt 100 ] - then - cat << EOF -style: success -value: $amount -ask: - en: A lot of donation this month: **$amount €** -EOF - else - cat << EOF -style: danger -value: $amount -ask: - en: Not so much donation this month: $amount € -EOF - fi -} - -get__prices() { - local prices = "$(grep "DONATION\['" "$final_path/settings.py" | sed -r "s@^DONATION\['([^']*)'\]\['([^']*)'\] = '([^']*)'@\1/\2/\3@g" | sed -z 's/\n/,/g;s/,$/\n/')" - if [ "$prices" == "," ]; - then - # Return YNH_NULL if you prefer to not return a value at all. - echo YNH_NULL - else - echo $prices - fi -} - - -#================================================= -# SPECIFIC VALIDATORS FOR TOML SHORT KEYS -#================================================= -validate__publishable_key() { - - # We can imagine here we test if the key is really a publisheable key - (is_secret_key $publishable_key) && - echo 'This key seems to be a secret key' -} - -#================================================= -# SPECIFIC SETTERS FOR TOML SHORT KEYS -#================================================= -set__prices() { - - #--------------------------------------------- - # IMPORTANT: setter are trigger only if a change is detected - #--------------------------------------------- - for price in $(echo $prices | sed "s/,/ /"); do - frequency=$(echo $price | cut -d/ -f1) - currency=$(echo $price | cut -d/ -f2) - price_id=$(echo $price | cut -d/ -f3) - sed "d/DONATION\['$frequency'\]\['$currency'\]" "$final_path/settings.py" - - echo "DONATION['$frequency']['$currency'] = '$price_id'" >> "$final_path/settings.py" - done - - #--------------------------------------------- - # IMPORTANT: to be able to upgrade properly, you have to saved the value in settings too - #--------------------------------------------- - ynh_app_setting_set $app prices $prices -} - -#================================================= -# GENERIC FINALIZATION -#================================================= -ynh_app_config_run $1 diff --git a/scripts/install b/scripts/install index a198a2a..71cfebc 100755 --- a/scripts/install +++ b/scripts/install @@ -10,170 +10,46 @@ source _common.sh source /usr/share/yunohost/helpers #================================================= -# MANAGE SCRIPT FAILURE -#================================================= - -ynh_clean_setup () { - ### Remove this function if there's nothing to clean before calling the remove script. - true -} -# Exit if an error occurs during the execution of the script -ynh_abort_if_errors - -#================================================= -# RETRIEVE ARGUMENTS FROM THE MANIFEST -#================================================= - -domain=$YNH_APP_ARG_DOMAIN -path_url=$YNH_APP_ARG_PATH -is_public=$YNH_APP_ARG_IS_PUBLIC -admin=$YNH_APP_ARG_ADMIN - -### 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 -#================================================= -### About --weight and --time -### ynh_script_progression will show to your final users the progression of each scripts. -### In order to do that, --weight will represent the relative time of execution compared to the other steps in the script. -### --time is a packager option, it will show you the execution time since the previous call. -### This option is implied when running in CI_package_check, you can manually add it if you are manually testing the app. -### Use the execution time displayed in the CI report or by adding --time to the command, to estimate the weight of a step. -### A common way to do it is to set a weight equal to the execution time in second +1. -### The execution time is given for the duration since the previous call. So the weight should be applied to this previous call. -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="/opt/yunohost/$app" -test ! -e "$final_path" || ynh_die --message="This path already contains a folder" - -# Register (book) web path -ynh_webpath_register --app=$app --domain=$domain --path_url=$path_url - -#================================================= -# STORE SETTINGS FROM MANIFEST -#================================================= -ynh_script_progression --message="Storing installation settings..." --weight=1 - -ynh_app_setting_set --app=$app --key=domain --value=$domain -ynh_app_setting_set --app=$app --key=path --value=$path_url - -#================================================= -# STANDARD MODIFICATIONS -#================================================= -# INSTALL DEPENDENCIES -#================================================= -ynh_script_progression --message="Installing dependencies..." --weight=1 - -### `ynh_install_app_dependencies` allows you to add any "apt" dependencies to the package. -### Those deb packages will be installed as dependencies of this package. -### If you're not using this helper: -### - Remove the section "REMOVE DEPENDENCIES" in the remove script -### - Remove the variable "pkg_dependencies" in _common.sh -### - As well as the section "REINSTALL DEPENDENCIES" in the restore script -### - And the section "UPGRADE DEPENDENCIES" in the upgrade script - -ynh_install_app_dependencies $pkg_dependencies - -#================================================= -# CREATE DEDICATED USER -#================================================= -ynh_script_progression --message="Configuring system user..." --weight=1 - -# Create a system user -ynh_system_user_create --username=$app --home_dir="$final_path" - +# 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 +ynh_exec_fully_quiet git clone -n "$repo_fullpath" "$install_dir/searxng-src" +pushd "$install_dir/searxng-src" + ynh_exec_fully_quiet git checkout "$commit_sha" +popd -ynh_app_setting_set --app=$app --key=final_path --value=$final_path -# Download, check integrity, uncompress and patch the source from app.src -ynh_setup_source --dest_dir="$final_path" - -# FIXME: this should be managed by the core in the future -# Here, as a packager, you may have to tweak the ownerhsip/permissions -# such that the appropriate users (e.g. maybe www-data) can access -# files in some cases. -# But FOR THE LOVE OF GOD, do not allow r/x for "others" on the entire folder - -# this will be treated as a security issue. -chmod 750 "$final_path" -chmod -R o-rwx "$final_path" -chown -R $app:www-data "$final_path" - -#================================================= -# NGINX CONFIGURATION -#================================================= -ynh_script_progression --message="Configuring NGINX web server..." --weight=1 - -### `ynh_add_nginx_config` will use the file conf/nginx.conf - -path_no_root=${path_url%/} -# Create a dedicated NGINX config -ynh_add_nginx_config "path_no_root" - -#================================================= -# SPECIFIC SETUP -#================================================= -# INSTALL SEARXNG IN A VIRTUALENV -#================================================= ynh_script_progression --message="Installing SearXNG..." --weight=2 -python3 -m venv --system-site-packages "$final_path/venv" -set +u; source $final_path/venv/bin/activate; set -u +python3 -m venv --system-site-packages "$install_dir/searxng-pyenv" +set +o nounset; source "$install_dir/searxng-pyenv/bin/activate"; set -o nounset pip3 install -U pip setuptools wheel pyyaml --no-cache-dir -pip3 install -e "$final_path" +ynh_exec_fully_quiet pip3 install -e "$install_dir/searxng-src" +#================================================= +# SYSTEM CONFIGURATION +#================================================= +ynh_script_progression --message="Adding system configurations related to $app..." --weight=1 + +ynh_add_nginx_config + +ynh_add_uwsgi_service + +#================================================= +# APP INITIAL CONFIGURATION #================================================= # ADD A CONFIGURATION #================================================= ynh_script_progression --message="Adding a configuration file..." --weight=1 secret_key=$(ynh_string_random) -full_url="https://$domain$path_url" -ynh_add_config --template="../conf/settings.yml" --destination="$final_path/searx/settings.yml" +ynh_add_config --template="../conf/settings.yml" --destination="$install_dir/settings.yml" -# 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 "$final_path/searx/settings.yml" -chown $app:$app "$final_path/searx/settings.yml" - -### 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="$final_path/some_config_file" -### ynh_store_file_checksum --file="$final_path/some_config_file" - -#### ADDED : SET PERMISSIONS ON SEARXNG DIRECTORY (CF SEARX SCRIPT) - -chown -R $app:$app $final_path - - -#================================================= -# CONFIGURE UWSGI FOR SEARX -#================================================= -ynh_script_progression --message="Configuring uWSGI for SearXNG..." --weight=2 - -ynh_add_uwsgi_service +chmod 750 "$install_dir" +chmod -R o-rwx "$install_dir" +chown -R $app: "$install_dir" #================================================= # GENERIC FINALIZATION @@ -182,36 +58,7 @@ ynh_add_uwsgi_service #================================================= 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=uwsgi-app@$app.service --action=start --log_path="/var/log/uwsgi/$app/$app.log" - -#================================================= -# SETUP SSOWAT -#================================================= -ynh_script_progression --message="Configuring permissions..." --weight=1 - -# Make app public if necessary -if [ $is_public -eq 1 ] -then - # Everyone can access the app. - # The "main" permission is automatically created before the install script. - ynh_permission_update --permission="main" --add="visitors" -fi - -#================================================= -# RELOAD NGINX -#================================================= -ynh_script_progression --message="Reloading NGINX web server..." --weight=1 - -ynh_systemd_action --service_name=nginx --action=reload +ynh_systemd_action --service_name="uwsgi-app@$app.service" --action="start" --line_match="WSGI app 0 \(mountpoint='[/[:alnum:]_-]*'\) ready in [[:digit:]]* seconds on interpreter" --log_path="/var/log/uwsgi/$app/$app.log" #================================================= # END OF SCRIPT diff --git a/scripts/remove b/scripts/remove index d8e4619..ef18fc1 100755 --- a/scripts/remove +++ b/scripts/remove @@ -10,59 +10,15 @@ source _common.sh source /usr/share/yunohost/helpers #================================================= -# LOAD SETTINGS +# REMOVE SYSTEM CONFIGURATIONS #================================================= -ynh_script_progression --message="Loading installation settings..." --weight=1 - -app=$YNH_APP_INSTANCE_NAME - -domain=$(ynh_app_setting_get --app=$app --key=domain) -final_path=$(ynh_app_setting_get --app=$app --key=final_path) - +# REMOVE SYSTEMD SERVICE #================================================= -# STANDARD REMOVE -#================================================= -# STOP AND REMOVE SERVICE -#================================================= -ynh_script_progression --message="Stopping and removing the systemd service..." --weight=1 +ynh_script_progression --message="Removing system configurations related to $app..." --weight=1 -# Remove the uwsgi and systemd configuration -ynh_systemd_action --service_name "uwsgi-app@$app.service" --action stop -ynh_remove_uwsgi_service - -#================================================= -# REMOVE APP MAIN DIR -#================================================= -ynh_script_progression --message="Removing app main directory..." --weight=1 - -# Remove the app directory securely -ynh_secure_remove --file="$final_path" - -#================================================= -# REMOVE NGINX CONFIGURATION -#================================================= -ynh_script_progression --message="Removing NGINX web server configuration..." --weight=1 - -# 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 - -#================================================= -# GENERIC FINALIZATION -#================================================= -# REMOVE DEDICATED USER -#================================================= -ynh_script_progression --message="Removing the dedicated system user..." --weight=1 - -# Delete a system user -ynh_system_user_delete --username=$app +ynh_remove_uwsgi_service #================================================= # END OF SCRIPT diff --git a/scripts/restore b/scripts/restore index 4ced8ff..1ac85c5 100755 --- a/scripts/restore +++ b/scripts/restore @@ -6,115 +6,38 @@ # IMPORT GENERIC HELPERS #================================================= -# Keep this path for calling _common.sh inside the execution's context of backup and restore scripts source ../settings/scripts/_common.sh source /usr/share/yunohost/helpers -#================================================= -# MANAGE SCRIPT FAILURE -#================================================= - -ynh_clean_setup () { - #### Remove this function if there's nothing to clean before calling the remove script. - true -} -# Exit if an error occurs during the execution of the script -ynh_abort_if_errors - -#================================================= -# LOAD SETTINGS -#================================================= -ynh_script_progression --message="Loading installation settings..." --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) -final_path=$(ynh_app_setting_get --app=$app --key=final_path) - -#================================================= -# CHECK IF THE APP CAN BE RESTORED -#================================================= -ynh_script_progression --message="Validating restoration parameters..." --weight=1 - -test ! -d $final_path \ - || ynh_die --message="There is already a directory: $final_path " - -#================================================= -# STANDARD RESTORATION STEPS -#================================================= -# RECREATE THE DEDICATED USER -#================================================= -ynh_script_progression --message="Recreating the dedicated system user..." --weight=1 - -# Create the dedicated user (if not existing) -ynh_system_user_create --username=$app --home_dir="$final_path" - #================================================= # RESTORE THE APP MAIN DIR #================================================= ynh_script_progression --message="Restoring the app main directory..." --weight=1 -ynh_restore_file --origin_path="$final_path" +ynh_restore_file --origin_path="$install_dir" -# FIXME: this should be managed by the core in the future -# Here, as a packager, you may have to tweak the ownerhsip/permissions -# such that the appropriate users (e.g. maybe www-data) can access -# files in some cases. -# But FOR THE LOVE OF GOD, do not allow r/x for "others" on the entire folder - -# this will be treated as a security issue. -chmod 750 "$final_path" -chmod -R o-rwx "$final_path" -chown -R $app:www-data "$final_path" +chown -R $app:www-data "$install_dir" +chmod 750 "$install_dir" +chmod -R o-rwx "$install_dir" #================================================= -# SPECIFIC RESTORATION +# RESTORE SYSTEM CONFIGURATIONS #================================================= -# REINSTALL DEPENDENCIES -#================================================= -ynh_script_progression --message="Reinstalling dependencies..." --weight=1 - -# Define and install dependencies -ynh_install_app_dependencies $pkg_dependencies - -#================================================= -# RESTORE THE NGINX CONFIGURATION -#================================================= -ynh_script_progression --message="Restoring the NGINX web server configuration..." --weight=1 ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" -#================================================= -# RESTORE VARIOUS FILES -#================================================= -ynh_script_progression --message="Restoring various files..." --weight=1 - -ynh_restore_file --origin_path="/etc/uwsgi/apps-available/$app.ini" - -mkdir -p "/var/log/uwsgi/$app" -chown $app:$app "/var/log/uwsgi/$app" -chmod u+rwX,g=rX,o= "/var/log/uwsgi/$app" - -ynh_check_global_uwsgi_config - -systemctl enable "uwsgi-app@$app.service" --quiet - -#================================================= -# START SYSTEMD SERVICE -#================================================= -ynh_script_progression --message="Starting a systemd service..." --weight=1 - -ynh_systemd_action --service_name=uwsgi-app@$app.service --action=start --line_match="spawned - uWSGI master process" --log_path="/var/log/uwsgi/$app/$app.log" +ynh_restore_uwsgi_service #================================================= # GENERIC FINALIZATION #================================================= -# RELOAD NGINX +# RELOAD NGINX AND PHP-FPM OR THE APP SERVICE #================================================= -ynh_script_progression --message="Reloading NGINX web server..." --weight=1 +ynh_script_progression --message="Reloading NGINX web server and $app's service..." --weight=1 -ynh_systemd_action --service_name=nginx --action=reload +ynh_systemd_action --service_name="uwsgi-app@$app.service" --action="start" --line_match="WSGI app 0 \(mountpoint='[/[:alnum:]_-]*'\) ready in [[:digit:]]* seconds on interpreter" --log_path="/var/log/uwsgi/$app/$app.log" + +ynh_systemd_action --service_name="nginx" --action="reload" #================================================= # END OF SCRIPT diff --git a/scripts/upgrade b/scripts/upgrade index f040dc2..d26e0ab 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -8,44 +8,8 @@ source _common.sh source /usr/share/yunohost/helpers - -#================================================= -# LOAD SETTINGS -#================================================= -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) -final_path=$(ynh_app_setting_get --app=$app --key=final_path) - -#================================================= -# CHECK VERSION -#================================================= - -### This helper will compare the version of the currently installed app and the version of the upstream package. -### $upgrade_type can have 2 different values -### - UPGRADE_APP if the upstream app version has changed -### - UPGRADE_PACKAGE if only the YunoHost package has changed -### ynh_check_app_version_changed will stop the upgrade if the app is up to date. -### UPGRADE_APP should be used to upgrade the core app only if there's an upgrade to do. upgrade_type=$(ynh_check_app_version_changed) -#================================================= -# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP -#================================================= -ynh_script_progression --message="Backing up the app before upgrading (may take a while)..." --weight=1 - -# Backup the current version of the app -ynh_backup_before_upgrade -ynh_clean_setup () { - # Restore it if the upgrade fails - ynh_restore_upgradebackup -} -# Exit if an error occurs during the execution of the script -ynh_abort_if_errors - #================================================= # STANDARD UPGRADE STEPS #================================================= @@ -53,36 +17,29 @@ ynh_abort_if_errors #================================================= ynh_script_progression --message="Ensuring downward compatibility..." --weight=1 -# -# N.B. : the followings setting migrations snippets are provided as *EXAMPLES* -# of what you may want to do in some cases (e.g. a setting was not defined on -# some legacy installs and you therefore want to initiaze stuff during upgrade) -# - -# If db_name doesn't exist, create it -#if [ -z "$db_name" ]; then -# db_name=$(ynh_sanitize_dbid --db_name=$app) -# ynh_app_setting_set --app=$app --key=db_name --value=$db_name -#fi - -# If final_path doesn't exist, create it -if [ -z "$final_path" ]; then - final_path=/var/www/$app - ynh_app_setting_set --app=$app --key=final_path --value=$final_path +if [ -e "$install_dir/searx" ]; then + tempdir="$(mktemp -d)" + mv "$install_dir/searx/settings.yml" "$tempdir/settings.yml" + sed -i '1s/^/use_default_settings: true\n\n/' "$tempdir/settings.yml" + ynh_secure_remove --file="$install_dir" + mkdir "$install_dir" + mv "$tempdir/settings.yml" "$install_dir/settings.yml" + ynh_secure_remove --file="$tempdir" + ynh_store_file_checksum --file="$install_dir/settings.yml" + ynh_delete_file_checksum --file="/opt/yunohost/$app/searx/settings.yml" fi -mkdir -p /var/log/uwsgi/$app -chown $app:$app /var/log/uwsgi/$app -chmod -R u=rwX,g=rX,o= /var/log/uwsgi/$app +ynh_delete_file_checksum --file="etc/nginx_conf.d/$domain/$app.conf" + +#================================================= +# STOP SYSTEMD SERVICE +#================================================= +ynh_script_progression --message="Stopping a systemd service..." --weight=1 + +ynh_systemd_action --service_name="uwsgi-app@$app.service" --action="stop" --log_path="/var/log/uwsgi/$app/$app.log" #================================================= -# CREATE DEDICATED USER -#================================================= -ynh_script_progression --message="Making sure dedicated system user exists..." --weight=1 - -# Create a dedicated user (if not existing) -ynh_system_user_create --username=$app --home_dir="$final_path" - +# "REBUILD" THE APP (DEPLOY NEW SOURCES, RERUN NPM BUILD...) #================================================= # DOWNLOAD, CHECK AND UNPACK SOURCE #================================================= @@ -91,91 +48,45 @@ if [ "$upgrade_type" == "UPGRADE_APP" ] then ynh_script_progression --message="Upgrading source files..." --weight=1 - # create a temporary directory - tmpdir=$(mktemp -d) - - # backup the config file in the temp dir - cp -a "$final_path/searx/settings.yml" "$tmpdir/settings.yml" - - # Download, check integrity, uncompress and patch the source from app.src - ynh_setup_source --dest_dir="$final_path" - - # Copy the saved settings back to final path - cp -a "$tmpdir/settings.yml" "$final_path/searx/settings.yml" - - # Remove the temporary directory safely - ynh_secure_remove --file="$tmpdir" + ynh_secure_remove --file="$install_dir/searxng-src" + ynh_exec_fully_quiet git clone -n "$repo_fullpath" "$install_dir/searxng-src" + pushd "$install_dir/searxng-src" + ynh_exec_fully_quiet git checkout "$commit_sha" + popd + + ynh_secure_remove --file="$install_dir/searxng-pyenv" + python3 -m venv --system-site-packages "$install_dir/searxng-pyenv" + set +o nounset; source "$install_dir/searxng-pyenv/bin/activate"; set -o nounset + pip3 install -U pip setuptools wheel pyyaml --no-cache-dir + ynh_exec_fully_quiet pip3 install -e "$install_dir/searxng-src" fi -# FIXME: this should be managed by the core in the future -# Here, as a packager, you may have to tweak the ownerhsip/permissions -# such that the appropriate users (e.g. maybe www-data) can access -# files in some cases. -# But FOR THE LOVE OF GOD, do not allow r/x for "others" on the entire folder - -# this will be treated as a security issue. -chmod 750 "$final_path" -chmod -R o-rwx "$final_path" -chown -R $app:www-data "$final_path" +chmod 750 "$install_dir" +chmod -R o-rwx "$install_dir" +chown -R $app: "$install_dir" #================================================= -# UPGRADE DEPENDENCIES +# REAPPLY SYSTEM CONFIGURATIONS #================================================= -ynh_script_progression --message="Upgrading dependencies..." --weight=1 +ynh_script_progression --message="Upgrading system configurations related to $app..." --weight=1 -ynh_install_app_dependencies $pkg_dependencies +ynh_add_nginx_config #================================================= -# NGINX CONFIGURATION +# RECONFIGURE THE APP (UPDATE CONF, APPLY MIGRATIONS...) #================================================= -ynh_script_progression --message="Upgrading NGINX web server configuration..." --weight=1 - -path_no_root=${path_url%/} -# Create a dedicated NGINX config -ynh_add_nginx_config "path_no_root" - +# UPDATE A CONFIG FILE #================================================= -# SPECIFIC UPGRADE -#================================================= -# UPGRADE SEARXNG IN ITS VIRTUALENV -#================================================= -ynh_script_progression --message="Upgrading SearXNG..." --weight=2 +ynh_script_progression --message="Updating a configuration file..." --weight=1 -ynh_secure_remove --file="$final_path/venv" - -python3 -m venv --system-site-packages "$final_path/venv" - -set +u; source $final_path/venv/bin/activate; set -u -pip3 install -U pip setuptools wheel pyyaml --no-cache-dir -pip3 install -e "$final_path" - -chown -R $app: "$final_path" - -#================================================= -# CONFIGURE UWSGI FOR SEARX -#================================================= -ynh_script_progression --message="Reconfiguring uWSGI for Searx..." --weight=2 - -# Clean old files -ynh_secure_remove --file="/etc/uwsgi/apps-enabled/$app.ini" -ynh_secure_remove --file="/etc/uwsgi/apps-available/$app.ini" ynh_add_uwsgi_service -#================================================= -# GENERIC FINALIZATION #================================================= # START SYSTEMD SERVICE #================================================= ynh_script_progression --message="Starting a systemd service..." --weight=1 - -# Wait for searx to be fully started -ynh_systemd_action --service_name=uwsgi-app@$app.service --action=restart --line_match="spawned uWSGI master process" --log_path="/var/log/uwsgi/$app/$app.log" - -#================================================= -# RELOAD NGINX -#================================================= -ynh_script_progression --message="Reloading NGINX web server..." --weight=1 - -ynh_systemd_action --service_name=nginx --action=reload + +ynh_systemd_action --service_name="uwsgi-app@$app.service" --action="start" --line_match="spawned uWSGI master process" --log_path="/var/log/uwsgi/$app/$app.log" #================================================= # END OF SCRIPT diff --git a/sources/extra_files/app/.gitignore b/sources/extra_files/app/.gitignore deleted file mode 100644 index 783a4ae..0000000 --- a/sources/extra_files/app/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*~ -*.sw[op] diff --git a/sources/patches/.gitignore b/sources/patches/.gitignore deleted file mode 100644 index 783a4ae..0000000 --- a/sources/patches/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*~ -*.sw[op] diff --git a/tests.toml b/tests.toml new file mode 100644 index 0000000..81dc0a3 --- /dev/null +++ b/tests.toml @@ -0,0 +1,22 @@ +#:schema https://raw.githubusercontent.com/YunoHost/apps/master/schemas/tests.v1.schema.json + +test_format = 1.0 + +[default] + + # ------------ + # Tests to run + # ------------ + + # ------------------------------- + # Default args to use for install + # ------------------------------- + + # ------------------------------- + # Commits to test upgrade from + # ------------------------------- + test_upgrade_from.9de9cc90.name = "2023.09.17.22.15.57~ynh1 / packaging v1" + test_upgrade_from.9de9cc90.args.domain = "domain.tld" + test_upgrade_from.9de9cc90.args.path = "/path" + test_upgrade_from.9de9cc90.args.is_public = 1 + test_upgrade_from.9de9cc90.args.admin = "john"