Merge pull request 'master' (#1) from Icycoide/searxng:master into master

Reviewed-on: #1
This commit is contained in:
kevadesu 2025-05-15 22:35:22 +02:00
commit 9f29131161
51 changed files with 1995 additions and 906 deletions

View file

@ -10,6 +10,12 @@ updates:
target-branch: "master" target-branch: "master"
commit-message: commit-message:
prefix: "[upd] pypi:" prefix: "[upd] pypi:"
groups:
minor:
applies-to: version-updates
update-types:
- "minor"
- "patch"
- package-ecosystem: "npm" - package-ecosystem: "npm"
directory: "/client/simple" directory: "/client/simple"
@ -20,3 +26,27 @@ updates:
target-branch: "master" target-branch: "master"
commit-message: commit-message:
prefix: "[upd] web-client (simple):" prefix: "[upd] web-client (simple):"
groups:
minor:
applies-to: version-updates
update-types:
- "minor"
- "patch"
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "weekly"
day: "friday"
target-branch: "master"
commit-message:
prefix: "[upd] docker:"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "friday"
target-branch: "master"
commit-message:
prefix: "[upd] github-actions:"

View file

@ -8,7 +8,7 @@ on:
- cron: "0 4 * * 5" - cron: "0 4 * * 5"
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }} group: ${{ github.workflow }}
cancel-in-progress: false cancel-in-progress: false
permissions: permissions:

34
.github/workflows/cleanup.yml vendored Normal file
View file

@ -0,0 +1,34 @@
---
name: Cleanup
# yamllint disable-line rule:truthy
on:
workflow_dispatch:
schedule:
- cron: "4 4 * * 0"
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
permissions:
contents: read
jobs:
container-cache:
name: Container cache
runs-on: ubuntu-24.04
permissions:
# Organization GHCR
packages: write
steps:
- name: Prune
uses: snok/container-retention-policy@v3.0.0
with:
account: "${{ github.repository_owner }}"
token: "${{ secrets.GITHUB_TOKEN }}"
image-names: "cache"
image-tags: "!searxng-*"
cut-off: "1w"
keep-n-most-recent: "100"

179
.github/workflows/container.yml vendored Normal file
View file

@ -0,0 +1,179 @@
---
name: Container
# yamllint disable-line rule:truthy
on:
workflow_dispatch:
workflow_run:
workflows:
- Integration
types:
- completed
branches:
- master
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
permissions:
contents: read
# Organization GHCR
packages: read
env:
PYTHON_VERSION: "3.13"
jobs:
build:
if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'
name: Build (${{ matrix.arch }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- arch: amd64
os: ubuntu-24.04
emulation: false
- arch: arm64
os: ubuntu-24.04-arm
emulation: false
- arch: armv7
os: ubuntu-24.04-arm
emulation: true
permissions:
# Organization GHCR
packages: write
outputs:
version_string: ${{ steps.build.outputs.version_string }}
version_tag: ${{ steps.build.outputs.version_tag }}
docker_tag: ${{ steps.build.outputs.docker_tag }}
git_url: ${{ steps.build.outputs.git_url }}
git_branch: ${{ steps.build.outputs.git_branch }}
steps:
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "${{ env.PYTHON_VERSION }}"
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: "false"
- name: Setup cache Python
uses: actions/cache@v4
with:
key: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
restore-keys: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-"
path: "./local/"
- name: Setup cache container mounts
uses: actions/cache@v4
with:
# yamllint disable-line rule:line-length
key: "container-mounts-${{ matrix.arch }}-${{ hashFiles('./container/Dockerfile', './container/legacy/Dockerfile') }}"
restore-keys: "container-mounts-${{ matrix.arch }}-"
path: |
/var/tmp/buildah-cache/
/var/tmp/buildah-cache-*/
- if: ${{ matrix.emulation }}
name: Setup QEMU
uses: docker/setup-qemu-action@v3
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: "ghcr.io"
username: "${{ github.repository_owner }}"
password: "${{ secrets.GITHUB_TOKEN }}"
- name: Build
id: build
env:
OVERRIDE_ARCH: "${{ matrix.arch }}"
run: make podman.build
test:
name: Test (${{ matrix.arch }})
runs-on: ${{ matrix.os }}
needs: build
strategy:
fail-fast: false
matrix:
include:
- arch: amd64
os: ubuntu-24.04
emulation: false
- arch: arm64
os: ubuntu-24.04-arm
emulation: false
- arch: armv7
os: ubuntu-24.04-arm
emulation: true
steps:
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: "false"
- if: ${{ matrix.emulation }}
name: Setup QEMU
uses: docker/setup-qemu-action@v3
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: "ghcr.io"
username: "${{ github.repository_owner }}"
password: "${{ secrets.GITHUB_TOKEN }}"
- name: Test
env:
OVERRIDE_ARCH: "${{ matrix.arch }}"
GIT_URL: "${{ needs.build.outputs.git_url }}"
run: make container.test
release:
if: github.repository_owner == 'searxng' && github.ref_name == 'master'
name: Release
runs-on: ubuntu-24.04-arm
needs:
- build
- test
permissions:
# Organization GHCR
packages: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: "false"
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: "ghcr.io"
username: "${{ github.repository_owner }}"
password: "${{ secrets.GITHUB_TOKEN }}"
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
registry: "docker.io"
username: "${{ secrets.DOCKERHUB_USERNAME }}"
password: "${{ secrets.DOCKERHUB_TOKEN }}"
- name: Release
env:
GIT_URL: "${{ needs.build.outputs.git_url }}"
DOCKER_TAG: "${{ needs.build.outputs.docker_tag }}"
run: make container.push

View file

@ -8,7 +8,7 @@ on:
- cron: "59 23 28 * *" - cron: "59 23 28 * *"
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }} group: ${{ github.workflow }}
cancel-in-progress: false cancel-in-progress: false
permissions: permissions:
@ -66,7 +66,7 @@ jobs:
id: cpr id: cpr
uses: peter-evans/create-pull-request@v7 uses: peter-evans/create-pull-request@v7
with: with:
author: "${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>" author: "searxng-bot <searxng-bot@users.noreply.github.com>"
committer: "searxng-bot <searxng-bot@users.noreply.github.com>" committer: "searxng-bot <searxng-bot@users.noreply.github.com>"
title: "[data] update searx.data - ${{ matrix.fetch }}" title: "[data] update searx.data - ${{ matrix.fetch }}"
commit-message: "[data] update searx.data - ${{ matrix.fetch }}" commit-message: "[data] update searx.data - ${{ matrix.fetch }}"
@ -74,6 +74,8 @@ jobs:
delete-branch: "true" delete-branch: "true"
draft: "false" draft: "false"
signoff: "false" signoff: "false"
body: |
[data] update searx.data - ${{ matrix.fetch }}
labels: | labels: |
data data

View file

@ -4,16 +4,15 @@ name: Documentation
# yamllint disable-line rule:truthy # yamllint disable-line rule:truthy
on: on:
workflow_dispatch: workflow_dispatch:
workflow_run: push:
workflows: branches:
- Integration - master
types: pull_request:
- completed
branches: branches:
- master - master
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }} group: ${{ github.workflow }}
cancel-in-progress: false cancel-in-progress: false
permissions: permissions:
@ -24,7 +23,6 @@ env:
jobs: jobs:
release: release:
if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'
name: Release name: Release
runs-on: ubuntu-24.04-arm runs-on: ubuntu-24.04-arm
permissions: permissions:
@ -56,7 +54,8 @@ jobs:
- name: Build documentation - name: Build documentation
run: make V=1 docs.clean docs.html run: make V=1 docs.clean docs.html
- name: Release - if: github.ref_name == 'master'
name: Release
uses: JamesIves/github-pages-deploy-action@v4 uses: JamesIves/github-pages-deploy-action@v4
with: with:
folder: "dist/docs" folder: "dist/docs"

View file

@ -1,136 +1,96 @@
---
name: Integration name: Integration
on: # yamllint disable-line rule:truthy # yamllint disable-line rule:truthy
on:
push: push:
branches: ["master"] branches:
- master
pull_request: pull_request:
branches: ["master"] branches:
- master
concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }}
cancel-in-progress: false
permissions: permissions:
contents: read contents: read
env:
PYTHON_VERSION: "3.13"
jobs: jobs:
python: test:
name: Python ${{ matrix.python-version }} name: Python ${{ matrix.python-version }}
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
strategy: strategy:
matrix: matrix:
os: [ubuntu-24.04] python-version:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] - "3.9"
- "3.10"
- "3.11"
- "3.12"
- "3.13"
steps: steps:
- name: Checkout - name: Setup Python
uses: actions/checkout@v4
- name: Install Ubuntu packages
run: |
sudo ./utils/searxng.sh install packages
- name: Set up Python
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: ${{ matrix.python-version }} python-version: "${{ matrix.python-version }}"
architecture: 'x64'
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: "false"
- name: Setup cache Python
uses: actions/cache@v4
with:
key: "python-${{ matrix.python-version }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
restore-keys: "python-${{ matrix.python-version }}-${{ runner.arch }}-"
path: "./local/"
- name: Setup venv
run: make V=1 install
- name: Run tests - name: Run tests
run: make V=1 ci.test run: make V=1 ci.test
themes: theme:
name: Themes name: Theme
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04-arm
steps: steps:
- name: Checkout - name: Setup Python
uses: actions/checkout@v4
- name: Install Ubuntu packages
run: sudo ./utils/searxng.sh install buildhost
- name: Set up Python
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: '3.12' python-version: "${{ env.PYTHON_VERSION }}"
architecture: 'x64'
- name: Build themes - name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: "false"
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: "./.nvmrc"
- name: Setup cache Node.js
uses: actions/cache@v4
with:
key: "nodejs-${{ runner.arch }}-${{ hashFiles('./.nvmrc', './package.json') }}"
path: "./client/simple/node_modules/"
- name: Setup cache Python
uses: actions/cache@v4
with:
key: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
restore-keys: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-"
path: "./local/"
- name: Setup venv
run: make V=1 install
- name: Build
run: make themes.all run: make themes.all
babel:
name: Update translations branch
runs-on: ubuntu-24.04
if: ${{ github.repository_owner == 'searxng' && github.ref == 'refs/heads/master' }}
needs:
- python
- themes
permissions:
contents: write # for make V=1 weblate.push.translations
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: '0'
token: ${{ secrets.WEBLATE_GITHUB_TOKEN }}
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
uses: actions/cache@v4
with:
path: |
./local
./.nvm
./node_modules
key: python-ubuntu-20.04-3.12-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
- name: weblate & git setup
env:
WEBLATE_CONFIG: ${{ secrets.WEBLATE_CONFIG }}
run: |
mkdir -p ~/.config
echo "${WEBLATE_CONFIG}" > ~/.config/weblate
git config --global user.email "searxng-bot@users.noreply.github.com"
git config --global user.name "searxng-bot"
- name: Update transations
id: update
run: |
make V=1 weblate.push.translations
dockers:
name: Docker
if: github.ref == 'refs/heads/master'
needs:
- python
- themes
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
runs-on: ubuntu-24.04
steps:
- name: Checkout
if: env.DOCKERHUB_USERNAME != null
uses: actions/checkout@v4
with:
# make sure "make docker.push" can get the git history
fetch-depth: '0'
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
uses: actions/cache@v4
with:
path: |
./local
./.nvm
./node_modules
key: python-ubuntu-20.04-3.12-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
- name: Set up QEMU
if: env.DOCKERHUB_USERNAME != null
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
if: env.DOCKERHUB_USERNAME != null
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
if: env.DOCKERHUB_USERNAME != null
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
if: env.DOCKERHUB_USERNAME != null
run: make -e GIT_URL=$(git remote get-url origin) docker.buildx

138
.github/workflows/l10n.yml vendored Normal file
View file

@ -0,0 +1,138 @@
---
name: Translation
# yamllint disable-line rule:truthy
on:
workflow_dispatch:
workflow_run:
workflows:
- Integration
types:
- completed
branches:
- master
schedule:
- cron: "05 07 * * 5"
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
permissions:
contents: read
env:
PYTHON_VERSION: "3.13"
jobs:
update:
if: github.repository_owner == 'searxng' && github.event.workflow_run.conclusion == 'success'
name: Update
runs-on: ubuntu-24.04-arm
permissions:
# For "make V=1 weblate.push.translations"
contents: write
steps:
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "${{ env.PYTHON_VERSION }}"
- name: Checkout
uses: actions/checkout@v4
with:
token: "${{ secrets.WEBLATE_GITHUB_TOKEN }}"
fetch-depth: "0"
- name: Setup cache Python
uses: actions/cache@v4
with:
key: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
restore-keys: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-"
path: "./local/"
- name: Setup venv
run: make V=1 install
- name: Setup Weblate
run: |
mkdir -p ~/.config
echo "${{ secrets.WEBLATE_CONFIG }}" > ~/.config/weblate
- name: Setup Git
run: |
git config --global user.email "searxng-bot@users.noreply.github.com"
git config --global user.name "searxng-bot"
- name: Update translations
run: make V=1 weblate.push.translations
pr:
if: |
github.repository_owner == 'searxng'
&& (github.event_name == 'workflow_dispatch' || github.event_name == 'schedule')
name: Pull Request
runs-on: ubuntu-24.04-arm
permissions:
# For "make V=1 weblate.translations.commit"
contents: write
# For action "peter-evans/create-pull-request"
pull-requests: write
steps:
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "${{ env.PYTHON_VERSION }}"
- name: Checkout
uses: actions/checkout@v4
with:
token: "${{ secrets.WEBLATE_GITHUB_TOKEN }}"
fetch-depth: "0"
- name: Setup cache Python
uses: actions/cache@v4
with:
key: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-${{ hashFiles('./requirements*.txt') }}"
restore-keys: "python-${{ env.PYTHON_VERSION }}-${{ runner.arch }}-"
path: "./local/"
- name: Setup venv
run: make V=1 install
- name: Setup Weblate
run: |
mkdir -p ~/.config
echo "${{ secrets.WEBLATE_CONFIG }}" > ~/.config/weblate
- name: Setup Git
run: |
git config --global user.email "searxng-bot@users.noreply.github.com"
git config --global user.name "searxng-bot"
- name: Merge and push translation updates
run: make V=1 weblate.translations.commit
- name: Create PR
id: cpr
uses: peter-evans/create-pull-request@v7
with:
author: "searxng-bot <searxng-bot@users.noreply.github.com>"
committer: "searxng-bot <searxng-bot@users.noreply.github.com>"
title: "[l10n] update translations from Weblate"
commit-message: "[l10n] update translations from Weblate"
branch: "translations_update"
delete-branch: "true"
draft: "false"
signoff: "false"
body: |
[l10n] update translations from Weblate
labels: |
translation
- name: Display information
run: |
echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}"

View file

@ -8,7 +8,7 @@ on:
- cron: "42 05 * * *" - cron: "42 05 * * *"
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }} group: ${{ github.workflow }}
cancel-in-progress: false cancel-in-progress: false
permissions: permissions:

View file

@ -1,59 +0,0 @@
name: "Update translations"
on: # yamllint disable-line rule:truthy
schedule:
- cron: "05 07 * * 5"
workflow_dispatch:
jobs:
babel:
name: "create PR for additions from weblate"
runs-on: ubuntu-24.04
if: ${{ github.repository_owner == 'searxng' && github.ref == 'refs/heads/master' }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: '0'
token: ${{ secrets.WEBLATE_GITHUB_TOKEN }}
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
uses: actions/cache@v4
with:
path: |
./local
./.nvm
./node_modules
key: python-ubuntu-24.04-3.12-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
- name: weblate & git setup
env:
WEBLATE_CONFIG: ${{ secrets.WEBLATE_CONFIG }}
run: |
mkdir -p ~/.config
echo "${WEBLATE_CONFIG}" > ~/.config/weblate
git config --global user.email "searxng-bot@users.noreply.github.com"
git config --global user.name "searxng-bot"
- name: Merge and push transation updates
run: |
make V=1 weblate.translations.commit
- name: Create Pull Request
id: cpr
uses: peter-evans/create-pull-request@v3
with:
token: ${{ secrets.WEBLATE_GITHUB_TOKEN }}
commit-message: '[l10n] update translations from Weblate'
committer: searxng-bot <searxng-bot@users.noreply.github.com>
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
signoff: false
branch: translations_update
delete-branch: true
draft: false
title: '[l10n] update translations from Weblate'
body: |
update translations from Weblate
labels: |
translation

View file

@ -54,7 +54,7 @@ ci.test: test.yamllint test.black test.types.ci test.pylint test.unit test.robo
test: test.yamllint test.black test.types.dev test.pylint test.unit test.robot test.rst test.shell test: test.yamllint test.black test.types.dev test.pylint test.unit test.robot test.rst test.shell
test.shell: test.shell:
$(Q)shellcheck -x -s dash \ $(Q)shellcheck -x -s dash \
dockerfiles/docker-entrypoint.sh container/docker-entrypoint.sh
$(Q)shellcheck -x -s bash \ $(Q)shellcheck -x -s bash \
utils/brand.sh \ utils/brand.sh \
$(MTOOLS) \ $(MTOOLS) \
@ -65,10 +65,7 @@ test.shell:
utils/lib_redis.sh \ utils/lib_redis.sh \
utils/searxng.sh \ utils/searxng.sh \
utils/lxc.sh \ utils/lxc.sh \
utils/lxc-searxng.env \ utils/lxc-searxng.env
utils/searx.sh \
utils/filtron.sh \
utils/morty.sh
$(Q)$(MTOOLS) build_msg TEST "$@ OK" $(Q)$(MTOOLS) build_msg TEST "$@ OK"
@ -77,7 +74,9 @@ test.shell:
MANAGE += weblate.translations.commit weblate.push.translations MANAGE += weblate.translations.commit weblate.push.translations
MANAGE += data.all data.traits data.useragents data.locales data.currencies MANAGE += data.all data.traits data.useragents data.locales data.currencies
MANAGE += docs.html docs.live docs.gh-pages docs.prebuild docs.clean MANAGE += docs.html docs.live docs.gh-pages docs.prebuild docs.clean
MANAGE += docker.build docker.push docker.buildx MANAGE += podman.build
MANAGE += docker.build docker.buildx
MANAGE += container.build container.test container.push
MANAGE += gecko.driver MANAGE += gecko.driver
MANAGE += node.env node.env.dev node.clean MANAGE += node.env node.env.dev node.clean
MANAGE += py.build py.clean MANAGE += py.build py.clean
@ -95,8 +94,8 @@ $(MANAGE):
# short hands of selected targets # short hands of selected targets
PHONY += docs docker themes PHONY += docs container themes
docs: docs.html docs: docs.html
docker: docker.build container: container.build
themes: themes.all themes: themes.all

File diff suppressed because it is too large Load diff

View file

@ -9,13 +9,13 @@
"icons.html": "node theme_icons.js" "icons.html": "node theme_icons.js"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.25.1", "@eslint/js": "^9.26.0",
"copy-webpack-plugin": "^13.0.0", "copy-webpack-plugin": "^13.0.0",
"css-loader": "^7.1.2", "css-loader": "^7.1.2",
"edge.js": "^6.2.1", "edge.js": "^6.2.1",
"eslint": "^9.25.1", "eslint": "^9.26.0",
"filemanager-webpack-plugin": "^8.0.0", "filemanager-webpack-plugin": "^8.0.0",
"globals": "^16.0.0", "globals": "^16.1.0",
"ionicons": "^8.0.8", "ionicons": "^8.0.8",
"leaflet": "^1.9.4", "leaflet": "^1.9.4",
"less": "^4.3.0", "less": "^4.3.0",
@ -29,10 +29,10 @@
"stylelint-prettier": "^5.0.3", "stylelint-prettier": "^5.0.3",
"svgo": "^3.3.2", "svgo": "^3.3.2",
"swiped-events": "^1.2.0", "swiped-events": "^1.2.0",
"vite": "^6.3.4", "vite": "^6.3.5",
"vite-plugin-static-copy": "^2.3.1", "vite-plugin-static-copy": "^2.3.1",
"vite-plugin-stylelint": "^6.0.0", "vite-plugin-stylelint": "^6.0.0",
"webpack": "^5.99.7", "webpack": "^5.99.8",
"webpack-cli": "^6.0.1" "webpack-cli": "^6.0.1"
}, },
"dependencies": { "dependencies": {

100
container/Dockerfile Normal file
View file

@ -0,0 +1,100 @@
FROM docker.io/library/python:3.13-slim AS builder
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
build-essential \
brotli \
# uwsgi
libpcre3-dev \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /usr/local/searxng/
COPY ./requirements.txt ./requirements.txt
RUN --mount=type=cache,id=pip,target=/root/.cache/pip python -m venv ./venv \
&& . ./venv/bin/activate \
&& pip install -r requirements.txt \
&& pip install "uwsgi~=2.0"
COPY ./searx/ ./searx/
ARG TIMESTAMP_SETTINGS=0
ARG TIMESTAMP_UWSGI=0
RUN python -m compileall -q searx \
&& touch -c --date=@$TIMESTAMP_SETTINGS ./searx/settings.yml \
&& touch -c --date=@$TIMESTAMP_UWSGI ./container/uwsgi.ini \
&& find /usr/local/searxng/searx/static \
\( -name '*.html' -o -name '*.css' -o -name '*.js' -o -name '*.svg' -o -name '*.ttf' -o -name '*.eot' \) \
-type f -exec gzip -9 -k {} + -exec brotli --best {} +
ARG SEARXNG_UID=977
ARG SEARXNG_GID=977
RUN grep -m1 root /etc/group > /tmp/.searxng.group \
&& grep -m1 root /etc/passwd > /tmp/.searxng.passwd \
&& echo "searxng:x:$SEARXNG_GID:" >> /tmp/.searxng.group \
&& echo "searxng:x:$SEARXNG_UID:$SEARXNG_GID:searxng:/usr/local/searxng:/bin/bash" >> /tmp/.searxng.passwd
FROM docker.io/library/python:3.13-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
# healthcheck
wget \
# uwsgi
libpcre3 \
libxml2 \
mailcap \
&& rm -rf /var/lib/apt/lists/*
COPY --chown=root:root --from=builder /tmp/.searxng.passwd /etc/passwd
COPY --chown=root:root --from=builder /tmp/.searxng.group /etc/group
ARG LABEL_DATE="0001-01-01T00:00:00Z"
ARG GIT_URL="unspecified"
ARG SEARXNG_GIT_VERSION="unspecified"
ARG LABEL_VCS_REF="unspecified"
ARG LABEL_VCS_URL="unspecified"
WORKDIR /usr/local/searxng/
COPY --chown=searxng:searxng --from=builder /usr/local/searxng/venv/ ./venv/
COPY --chown=searxng:searxng --from=builder /usr/local/searxng/searx/ ./searx/
COPY --chown=searxng:searxng ./container/ ./container/
LABEL org.opencontainers.image.authors="searxng <$GIT_URL>" \
org.opencontainers.image.created=$LABEL_DATE \
org.opencontainers.image.description="A privacy-respecting, hackable metasearch engine" \
org.opencontainers.image.documentation="https://github.com/searxng/searxng-docker" \
org.opencontainers.image.licenses="AGPL-3.0-or-later" \
org.opencontainers.image.revision=$LABEL_VCS_REF \
org.opencontainers.image.source=$LABEL_VCS_URL \
org.opencontainers.image.title="searxng" \
org.opencontainers.image.url=$LABEL_VCS_URL \
org.opencontainers.image.version=$SEARXNG_GIT_VERSION
ENV CONFIG_PATH=/etc/searxng \
DATA_PATH=/var/cache/searxng
ENV SEARXNG_VERSION=$SEARXNG_GIT_VERSION \
INSTANCE_NAME=searxng \
AUTOCOMPLETE="" \
BASE_URL="" \
BIND_ADDRESS=[::]:8080 \
MORTY_KEY="" \
MORTY_URL="" \
SEARXNG_SETTINGS_PATH=$CONFIG_PATH/settings.yml \
UWSGI_SETTINGS_PATH=$CONFIG_PATH/uwsgi.ini \
UWSGI_WORKERS=%k \
UWSGI_THREADS=4
VOLUME $CONFIG_PATH
VOLUME $DATA_PATH
EXPOSE 8080
HEALTHCHECK CMD wget --quiet --tries=1 --spider http://localhost:8080/healthz || exit 1
ENTRYPOINT ["/usr/local/searxng/container/docker-entrypoint.sh"]

View file

@ -12,8 +12,7 @@ Environment variables:
INSTANCE_NAME settings.yml : general.instance_name INSTANCE_NAME settings.yml : general.instance_name
AUTOCOMPLETE settings.yml : search.autocomplete AUTOCOMPLETE settings.yml : search.autocomplete
BASE_URL settings.yml : server.base_url BASE_URL settings.yml : server.base_url
MORTY_URL settings.yml : result_proxy.url
MORTY_KEY settings.yml : result_proxy.key
Volume: Volume:
/etc/searxng the docker entry point copies settings.yml and uwsgi.ini in /etc/searxng the docker entry point copies settings.yml and uwsgi.ini in
this directory (see the -f command line option)" this directory (see the -f command line option)"
@ -70,20 +69,6 @@ patch_searxng_settings() {
-e "s/autocomplete: \"\"/autocomplete: \"${AUTOCOMPLETE}\"/g" \ -e "s/autocomplete: \"\"/autocomplete: \"${AUTOCOMPLETE}\"/g" \
-e "s/ultrasecretkey/$(head -c 24 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9')/g" \ -e "s/ultrasecretkey/$(head -c 24 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9')/g" \
"${CONF}" "${CONF}"
# Morty configuration
if [ -n "${MORTY_KEY}" ] && [ -n "${MORTY_URL}" ]; then
sed -i -e "s/image_proxy: false/image_proxy: true/g" \
"${CONF}"
cat >> "${CONF}" <<-EOF
# Morty configuration
result_proxy:
url: ${MORTY_URL}
key: !!binary "${MORTY_KEY}"
EOF
fi
} }
update_conf() { update_conf() {
@ -122,32 +107,8 @@ update_conf() {
fi fi
} }
# searx compatibility: copy /etc/searx/* to /etc/searxng/*
SEARX_CONF=0
if [ -f "/etc/searx/settings.yml" ]; then
if [ ! -f "${SEARXNG_SETTINGS_PATH}" ]; then
printf '⚠️ /etc/searx/settings.yml is copied to /etc/searxng\n'
cp "/etc/searx/settings.yml" "${SEARXNG_SETTINGS_PATH}"
fi
SEARX_CONF=1
fi
if [ -f "/etc/searx/uwsgi.ini" ]; then
printf '⚠️ /etc/searx/uwsgi.ini is ignored. Use the volume /etc/searxng\n'
SEARX_CONF=1
fi
if [ "$SEARX_CONF" -eq "1" ]; then
printf '⚠️ The deprecated volume /etc/searx is mounted. Please update your configuration to use /etc/searxng ⚠️\n'
cat << EOF > /etc/searx/deprecated_volume_read_me.txt
This Docker image uses the volume /etc/searxng
Update your configuration:
* remove uwsgi.ini (or very carefully update your existing uwsgi.ini using https://github.com/searxng/searxng/blob/master/dockerfiles/uwsgi.ini )
* mount /etc/searxng instead of /etc/searx
EOF
fi
# end of searx compatibility
# make sure there are uwsgi settings # make sure there are uwsgi settings
update_conf "${FORCE_CONF_UPDATE}" "${UWSGI_SETTINGS_PATH}" "/usr/local/searxng/dockerfiles/uwsgi.ini" "patch_uwsgi_settings" update_conf "${FORCE_CONF_UPDATE}" "${UWSGI_SETTINGS_PATH}" "/usr/local/searxng/container/uwsgi.ini" "patch_uwsgi_settings"
# make sure there are searxng settings # make sure there are searxng settings
update_conf "${FORCE_CONF_UPDATE}" "${SEARXNG_SETTINGS_PATH}" "/usr/local/searxng/searx/settings.yml" "patch_searxng_settings" update_conf "${FORCE_CONF_UPDATE}" "${SEARXNG_SETTINGS_PATH}" "/usr/local/searxng/searx/settings.yml" "patch_searxng_settings"
@ -158,8 +119,6 @@ if [ $DRY_RUN -eq 1 ]; then
exit exit
fi fi
unset MORTY_KEY
printf 'Listen on %s\n' "${BIND_ADDRESS}" printf 'Listen on %s\n' "${BIND_ADDRESS}"
# Start uwsgi # Start uwsgi

View file

@ -1,3 +1,5 @@
# For armv7 architecture
FROM docker.io/library/python:3.13-slim AS builder FROM docker.io/library/python:3.13-slim AS builder
RUN apt-get update \ RUN apt-get update \
@ -16,8 +18,7 @@ WORKDIR /usr/local/searxng/
COPY ./requirements.txt ./requirements.txt COPY ./requirements.txt ./requirements.txt
# Readd on #4707 "--mount=type=cache,id=pip,target=/root/.cache/pip" RUN --mount=type=cache,id=pip,target=/root/.cache/pip python -m venv ./venv \
RUN python -m venv ./venv \
&& . ./venv/bin/activate \ && . ./venv/bin/activate \
&& pip install -r requirements.txt \ && pip install -r requirements.txt \
&& pip install "uwsgi~=2.0" && pip install "uwsgi~=2.0"
@ -29,7 +30,7 @@ ARG TIMESTAMP_UWSGI=0
RUN python -m compileall -q searx \ RUN python -m compileall -q searx \
&& touch -c --date=@$TIMESTAMP_SETTINGS ./searx/settings.yml \ && touch -c --date=@$TIMESTAMP_SETTINGS ./searx/settings.yml \
&& touch -c --date=@$TIMESTAMP_UWSGI ./dockerfiles/uwsgi.ini \ && touch -c --date=@$TIMESTAMP_UWSGI ./container/uwsgi.ini \
&& find /usr/local/searxng/searx/static \ && find /usr/local/searxng/searx/static \
\( -name '*.html' -o -name '*.css' -o -name '*.js' -o -name '*.svg' -o -name '*.ttf' -o -name '*.eot' \) \ \( -name '*.html' -o -name '*.css' -o -name '*.js' -o -name '*.svg' -o -name '*.ttf' -o -name '*.eot' \) \
-type f -exec gzip -9 -k {} + -exec brotli --best {} + -type f -exec gzip -9 -k {} + -exec brotli --best {} +
@ -69,7 +70,7 @@ WORKDIR /usr/local/searxng/
COPY --chown=searxng:searxng --from=builder /usr/local/searxng/venv/ ./venv/ COPY --chown=searxng:searxng --from=builder /usr/local/searxng/venv/ ./venv/
COPY --chown=searxng:searxng --from=builder /usr/local/searxng/searx/ ./searx/ COPY --chown=searxng:searxng --from=builder /usr/local/searxng/searx/ ./searx/
COPY --chown=searxng:searxng ./dockerfiles/ ./dockerfiles/ COPY --chown=searxng:searxng ./container/ ./container/
LABEL org.opencontainers.image.authors="searxng <$GIT_URL>" \ LABEL org.opencontainers.image.authors="searxng <$GIT_URL>" \
org.opencontainers.image.created=$LABEL_DATE \ org.opencontainers.image.created=$LABEL_DATE \
@ -90,8 +91,6 @@ ENV SEARXNG_VERSION=$SEARXNG_GIT_VERSION \
AUTOCOMPLETE="" \ AUTOCOMPLETE="" \
BASE_URL="" \ BASE_URL="" \
BIND_ADDRESS=[::]:8080 \ BIND_ADDRESS=[::]:8080 \
MORTY_KEY="" \
MORTY_URL="" \
SEARXNG_SETTINGS_PATH=$CONFIG_PATH/settings.yml \ SEARXNG_SETTINGS_PATH=$CONFIG_PATH/settings.yml \
UWSGI_SETTINGS_PATH=$CONFIG_PATH/uwsgi.ini \ UWSGI_SETTINGS_PATH=$CONFIG_PATH/uwsgi.ini \
UWSGI_WORKERS=%k \ UWSGI_WORKERS=%k \
@ -104,4 +103,4 @@ EXPOSE 8080
HEALTHCHECK CMD wget --quiet --tries=1 --spider http://localhost:8080/healthz || exit 1 HEALTHCHECK CMD wget --quiet --tries=1 --spider http://localhost:8080/healthz || exit 1
ENTRYPOINT ["/usr/local/searxng/dockerfiles/docker-entrypoint.sh"] ENTRYPOINT ["/usr/local/searxng/container/docker-entrypoint.sh"]

View file

@ -6,7 +6,7 @@ digraph G {
browser [label="browser", shape=tab, fillcolor=aliceblue]; browser [label="browser", shape=tab, fillcolor=aliceblue];
rp [label="reverse proxy"]; rp [label="reverse proxy"];
static [label="static files", shape=folder, href="url to configure static files", fillcolor=lightgray]; static [label="static files", shape=folder, href="url to configure static files", fillcolor=lightgray];
uwsgi [label="uwsgi", shape=parallelogram href="https://docs.searxng.org/utils/searx.sh.html"] uwsgi [label="uwsgi", shape=parallelogram href="https://docs.searxng.org/utils/searxng.sh.html"]
redis [label="redis DB", shape=cylinder]; redis [label="redis DB", shape=cylinder];
searxng1 [label="SearXNG #1", fontcolor=blue3]; searxng1 [label="SearXNG #1", fontcolor=blue3];
searxng2 [label="SearXNG #2", fontcolor=blue3]; searxng2 [label="SearXNG #2", fontcolor=blue3];

View file

@ -145,13 +145,6 @@ shell inside container
- `How to make bash scripts work in dash <http://mywiki.wooledge.org/Bashism>`_ - `How to make bash scripts work in dash <http://mywiki.wooledge.org/Bashism>`_
- `Checking for Bashisms <https://dev.to/bowmanjd/writing-bash-scripts-that-are-not-only-bash-checking-for-bashisms-and-testing-with-dash-1bli>`_ - `Checking for Bashisms <https://dev.to/bowmanjd/writing-bash-scripts-that-are-not-only-bash-checking-for-bashisms-and-testing-with-dash-1bli>`_
Like in many other distributions, Alpine's `/bin/sh
<https://wiki.ubuntu.com/DashAsBinSh>`__ is :man:`dash`. Dash is meant to be
`POSIX-compliant <https://pubs.opengroup.org/onlinepubs/9699919799>`__.
Compared to debian, in the Alpine image :man:`bash` is not installed. The
:origin:`dockerfiles/docker-entrypoint.sh` script is checked *against dash*
(``make tests.shell``).
To open a shell inside the container: To open a shell inside the container:
.. code:: sh .. code:: sh
@ -188,10 +181,10 @@ Command line
<https://docs.docker.com/engine/reference/run/#foreground>`__. <https://docs.docker.com/engine/reference/run/#foreground>`__.
In the :origin:`Dockerfile` the ENTRYPOINT_ is defined as In the :origin:`Dockerfile` the ENTRYPOINT_ is defined as
:origin:`dockerfiles/docker-entrypoint.sh` :origin:`container/docker-entrypoint.sh`
.. code:: sh .. code:: sh
docker run --rm -it searxng/searxng -h docker run --rm -it searxng/searxng -h
.. program-output:: ../dockerfiles/docker-entrypoint.sh -h .. program-output:: ../container/docker-entrypoint.sh -h

View file

@ -58,9 +58,6 @@ and then, to name just a few:
- Bot protection has been switched from filtron to SearXNG's :ref:`limiter - Bot protection has been switched from filtron to SearXNG's :ref:`limiter
<limiter>`, this requires a :ref:`Redis <settings redis>` database. <limiter>`, this requires a :ref:`Redis <settings redis>` database.
- The image proxy morty is no longer needed, it has been replaced by the
:ref:`image proxy <image_proxy>` from SearXNG.
- To save bandwidth :ref:`cache busting <static_use_hash>` has been implemented. - To save bandwidth :ref:`cache busting <static_use_hash>` has been implemented.
To get in use, the ``static-expires`` needs to be set in the :ref:`uwsgi To get in use, the ``static-expires`` needs to be set in the :ref:`uwsgi
setup`. setup`.
@ -71,12 +68,6 @@ examples show, this is not always enough, sometimes services have to be set up
or reconfigured and sometimes services that are no longer needed should be or reconfigured and sometimes services that are no longer needed should be
uninstalled. uninstalled.
.. hint::
First of all: SearXNG is installed by the script :ref:`searxng.sh`. If you
have old filtron, morty or searx setup you should consider complete
uninstall/reinstall.
Here you will find a list of changes that affect the infrastructure. Please Here you will find a list of changes that affect the infrastructure. Please
check to what extent it is necessary to update your installations: check to what extent it is necessary to update your installations:
@ -85,39 +76,6 @@ check to what extent it is necessary to update your installations:
file manually. file manually.
remove obsolete services
------------------------
If your searx instance was installed *"Step by step"* or by the *"Installation
scripts"*, you need to undo the installation procedure completely. If you have
morty & filtron installed, it is recommended to uninstall these services also.
In case of scripts, to uninstall use the scripts from the origin you installed
searx from or try::
$ sudo -H ./utils/filtron.sh remove all
$ sudo -H ./utils/morty.sh remove all
$ sudo -H ./utils/searx.sh remove all
.. hint::
If you are migrate from searx take into account that the ``.config.sh`` is no
longer used.
If you upgrade from searx or from before :pull:`1332` has been merged and you
have filtron and/or morty installed, don't forget to remove HTTP sites.
Apache::
$ sudo -H ./utils/filtron.sh apache remove
$ sudo -H ./utils/morty.sh apache remove
nginx::
$ sudo -H ./utils/filtron.sh nginx remove
$ sudo -H ./utils/morty.sh nginx remove
Check after Installation Check after Installation
------------------------ ------------------------
@ -130,9 +88,6 @@ to see if there are some left overs. In this example there exists a *old*
SearXNG checks SearXNG checks
-------------- --------------
ERROR: settings.yml in /etc/searx/ is deprecated, move file to folder /etc/searxng/ ERROR: settings.yml in /etc/searx/ is deprecated, move file to folder /etc/searxng/
INFO: [OK] (old) account 'searx' does not exists
INFO: [OK] (old) account 'filtron' does not exists
INFO: [OK] (old) account 'morty' does not exists
... ...
INFO searx.redisdb : connecting to Redis db=0 path='/usr/local/searxng-redis/run/redis.sock' INFO searx.redisdb : connecting to Redis db=0 path='/usr/local/searxng-redis/run/redis.sock'
INFO searx.redisdb : connected to Redis INFO searx.redisdb : connected to Redis

108
docs/dev/commits.rst Normal file
View file

@ -0,0 +1,108 @@
.. _create commit:
===============================
Git Commits & Change Management
===============================
.. sidebar:: Create good commits!
- `Conventional Commits`_
- `Structural split of changes`_
- `Git Commit Good Practice`_
A commit and its commit message are among the most important information
available to a developer for bug fixing and further development. A commit is a
change and changes have a context (a change request).
In a SCM system (git), the change history is derived from the commit history. A
commit message is therefore part of the documentation for change management and
thus elementary for the traceability of changes.
**What a commit is not**: *A commit to an SCM system is not used to save files!*
A commit should always have a context and the commit message describes what is
to be changed in that context, just as a function description should describe
what the intention and the goal of the function is, a commit message should
describe what the intention and the goal of that commit is.
The commit messages form the history and are the first and therefore most
important information a developer has when he has to research when and why a
change had to be made and how it was made (what the goal was).
Like any text, a commit message should be written for the reader and not from
the perspective of the author.
When scrolling through the history, the first thing one see is the title of the
commit message. Therefore the title should describe the change as briefly and
precisely as possible ... followed by a blank line and then a somewhat detailed
description of the change.
----
The follwing rules should be in mind, when creating a commit:
- **Commit history should be read like a history book.**
- **Commit messages are for the reader not for the author of the commit.**
- **A commit is the atomic code-modification of a change in change management.**
- **Think about which descriptions from your PR might belong in the commit message.**
- **The maximum line length in a commit message is 80 characters.**
----
Choose meaningful commit messages:
.. code::
[type] optional scope: description
[body]
[optional trailers]
``[type]``:
Commits MUST be prefixed with a type .. ``feat``, ``fix``, ``refactor``,
``mod``, ``upd``, ``doc``, ``l10n``, ``build`` ..
``[body]``
`Information in commit messages`_
``[optional trailers]``:
- `Signed-off-by`_: certify that the committer has the rights to submit the
work under the projects license. That the developer has this right is a
prerequisite for a merge. If the `Signed-off-by`_ is not set in the
commit, the contributor enters his `Developer's Certificate of Origin` at
the latest when creating a PR!
- Closes: Link to the bug report or the bug number (e.g. ``Closes: #10``)
- `Co-authored-by`_: email address of the co-author
- Reported-by: email address (if there is no bug report)
- Suggested-by: email address (if there is no bug report)
----
To give examples at hand, here are a few commits. Follow the links to see the
full commit messages:
:patch:`44d941c93`
``[fix] mojeek web engine: don't add empty fmt argument for web searches``
:patch:`feb15e387`
``[fix] brave.news engine: response is HTML and no longer JSON``
:patch:`bdfe1c2a1`
``[mod] engines: migration of the individual cache solutions to EngineCache``
.. _Conventional Commits:
https://www.conventionalcommits.org/
.. _Structural split of changes:
https://wiki.openstack.org/wiki/GitCommitMessages#Structural_split_of_changes
.. _Git Commit Good Practice:
https://wiki.openstack.org/wiki/GitCommitMessages
.. _Information in commit messages:
https://wiki.openstack.org/wiki/GitCommitMessages#Information_in_commit_messages
.. _`Developer's Certificate of Origin`:
https://developercertificate.org/
.. _Signed-off-by:
https://git-scm.com/docs/git-commit#Documentation/git-commit.txt-code--signoffcode
.. _Co-authored-by:
https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/creating-a-commit-with-multiple-authors

View file

@ -56,20 +56,12 @@ Code
==== ====
.. _PEP8: https://www.python.org/dev/peps/pep-0008/ .. _PEP8: https://www.python.org/dev/peps/pep-0008/
.. _Conventional Commits: https://www.conventionalcommits.org/
.. _Git Commit Good Practice: https://wiki.openstack.org/wiki/GitCommitMessages
.. _Structural split of changes: .. _Structural split of changes:
https://wiki.openstack.org/wiki/GitCommitMessages#Structural_split_of_changes https://wiki.openstack.org/wiki/GitCommitMessages#Structural_split_of_changes
.. _gitmoji: https://gitmoji.carloscuesta.me/
.. _Semantic PR: https://github.com/zeke/semantic-pull-requests
.. sidebar:: Create good commits! .. sidebar:: Create good commits!
- `Structural split of changes`_ - :ref:`create commit`
- `Conventional Commits`_
- `Git Commit Good Practice`_
- some like to use: gitmoji_
- not yet active: `Semantic PR`_
In order to submit a patch, please follow the steps below: In order to submit a patch, please follow the steps below:
@ -88,15 +80,7 @@ In order to submit a patch, please follow the steps below:
- Add yourself to the :origin:`AUTHORS.rst` file. - Add yourself to the :origin:`AUTHORS.rst` file.
- Choose meaningful commit messages, read `Conventional Commits`_ - Choose meaningful commit messages, see :ref:`create commit`
.. code::
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
- Create a pull request. - Create a pull request.

View file

@ -6,6 +6,7 @@ Developer documentation
:maxdepth: 2 :maxdepth: 2
quickstart quickstart
commits
rtm_asdf rtm_asdf
contribution_guide contribution_guide
extended_types extended_types

View file

@ -319,13 +319,13 @@ To *inspect* the SearXNG instance (already described above):
.. code:: bash .. code:: bash
$ ./utils/searx.sh inspect service $ ./utils/searxng.sh inspect service
.. group-tab:: desktop (HOST) .. group-tab:: desktop (HOST)
.. code:: bash .. code:: bash
$ sudo -H ./utils/lxc.sh cmd searxng-archlinux ./utils/searx.sh inspect service $ sudo -H ./utils/lxc.sh cmd searxng-archlinux ./utils/searxng.sh inspect service
Run :ref:`makefile`, e.g. to test inside the container: Run :ref:`makefile`, e.g. to test inside the container:
@ -435,4 +435,3 @@ use:
[searxng-archlinux] SEARXNG_URL : http:///n.n.n.140/searxng [searxng-archlinux] SEARXNG_URL : http:///n.n.n.140/searxng
[searxng-archlinux] SEARXNG_PORT : 8888 [searxng-archlinux] SEARXNG_PORT : 8888
[searxng-archlinux] SEARXNG_BIND_ADDRESS : 127.0.0.1 [searxng-archlinux] SEARXNG_BIND_ADDRESS : 127.0.0.1

View file

@ -39,8 +39,7 @@ Removing private data means not sending cookies to external search engines and
generating a random browser profile for every request. Thus, it does not matter generating a random browser profile for every request. Thus, it does not matter
if a public or private instance handles the request, because it is anonymized in if a public or private instance handles the request, because it is anonymized in
both cases. The IP address used will be the IP of the instance, but SearXNG can also be both cases. The IP address used will be the IP of the instance, but SearXNG can also be
configured to use proxy or Tor. `Result proxy configured to use proxy or Tor.
<https://github.com/asciimoo/morty>`__ is supported, too.
SearXNG does not serve ads or tracking content, unlike most search services. Therefore, SearXNG does not serve ads or tracking content, unlike most search services. Therefore,
private data is not forwarded to third parties who might monetize it. Besides private data is not forwarded to third parties who might monetize it. Besides

View file

@ -28,7 +28,7 @@ In most cases you will install SearXNG simply by running the command:
.. code:: bash .. code:: bash
sudo -H ./utils/searx.sh install all sudo -H ./utils/searxng.sh install all
The installation is described in chapter :ref:`installation basic`. The installation is described in chapter :ref:`installation basic`.

91
manage
View file

@ -11,6 +11,9 @@ source "$(dirname "${BASH_SOURCE[0]}")/utils/lib.sh"
# shellcheck source=utils/lib.sh # shellcheck source=utils/lib.sh
source "$(dirname "${BASH_SOURCE[0]}")/utils/lib_nvm.sh" source "$(dirname "${BASH_SOURCE[0]}")/utils/lib_nvm.sh"
# shellcheck source=utils/lib_sxng_container.sh
source "$(dirname "${BASH_SOURCE[0]}")/utils/lib_sxng_container.sh"
# shellcheck source=utils/lib_sxng_data.sh # shellcheck source=utils/lib_sxng_data.sh
source "$(dirname "${BASH_SOURCE[0]}")/utils/lib_sxng_data.sh" source "$(dirname "${BASH_SOURCE[0]}")/utils/lib_sxng_data.sh"
@ -77,9 +80,6 @@ docs.:
gh-pages : deploy on gh-pages branch gh-pages : deploy on gh-pages branch
prebuild : build reST include files (./${DOCS_BUILD}/includes) prebuild : build reST include files (./${DOCS_BUILD}/includes)
clean : clean documentation build clean : clean documentation build
docker.:
build : build docker image
push : build and push docker image
gecko.driver: gecko.driver:
download & install geckodriver if not already installed (required for download & install geckodriver if not already installed (required for
robot_tests) robot_tests)
@ -101,6 +101,7 @@ EOF
go.help go.help
node.help node.help
weblate.help weblate.help
container.help
data.help data.help
test.help test.help
themes.help themes.help
@ -136,90 +137,6 @@ webapp.run() {
SEARXNG_DEBUG=1 pyenv.cmd python -m searx.webapp SEARXNG_DEBUG=1 pyenv.cmd python -m searx.webapp
} }
docker.push() {
docker.build push
}
docker.buildx() {
docker.build buildx
}
# shellcheck disable=SC2119
docker.build() {
pyenv.install
local SEARXNG_GIT_VERSION
local VERSION_GITCOMMIT
local GITHUB_USER
local SEARXNG_IMAGE_NAME
local BUILD
build_msg DOCKER build
# run installation in a subprocess and activate pyenv
# See https://www.shellcheck.net/wiki/SC1001 and others ..
# shellcheck disable=SC2031,SC2230,SC2002,SC2236,SC2143,SC1001
( set -e
pyenv.activate
# Check if it is a git repository
if [ ! -d .git ]; then
die 1 "This is not Git repository"
fi
if [ ! -x "$(which git)" ]; then
die 1 "git is not installed"
fi
if ! git remote get-url origin 2> /dev/null; then
die 1 "there is no remote origin"
fi
# This is a git repository
git update-index -q --refresh
python -m searx.version freeze
eval "$(python -m searx.version)"
# Get the last git commit id
VERSION_GITCOMMIT=$(echo "$VERSION_TAG" | cut -d+ -f2)
build_msg DOCKER "Last commit : $VERSION_GITCOMMIT"
# define the docker image name
GITHUB_USER=$(echo "${GIT_URL}" | sed 's/.*github\.com\/\([^\/]*\).*/\1/')
SEARXNG_IMAGE_NAME="${SEARXNG_IMAGE_NAME:-${GITHUB_USER:-searxng}/searxng}"
BUILD="build"
if [ "$1" = "buildx" ]; then
# buildx includes the push option
CACHE_TAG="${SEARXNG_IMAGE_NAME}:latest-build-cache"
BUILD="buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 --push --cache-from=type=registry,ref=$CACHE_TAG --cache-to=type=registry,ref=$CACHE_TAG,mode=max"
shift
fi
build_msg DOCKER "Build command: ${BUILD}"
# build Docker image
build_msg DOCKER "Building image ${SEARXNG_IMAGE_NAME}:${SEARXNG_GIT_VERSION}"
# shellcheck disable=SC2086
docker $BUILD \
--build-arg BASE_IMAGE="${DEPENDENCIES_IMAGE_NAME}" \
--build-arg GIT_URL="${GIT_URL}" \
--build-arg SEARXNG_DOCKER_TAG="${DOCKER_TAG}" \
--build-arg SEARXNG_GIT_VERSION="${VERSION_STRING}" \
--build-arg VERSION_GITCOMMIT="${VERSION_GITCOMMIT}" \
--build-arg LABEL_DATE="$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
--build-arg LABEL_VCS_REF="$(git rev-parse HEAD)" \
--build-arg LABEL_VCS_URL="${GIT_URL}" \
--build-arg TIMESTAMP_SETTINGS="$(git log -1 --format="%cd" --date=unix -- searx/settings.yml)" \
--build-arg TIMESTAMP_UWSGI="$(git log -1 --format="%cd" --date=unix -- dockerfiles/uwsgi.ini)" \
-t "${SEARXNG_IMAGE_NAME}:latest" -t "${SEARXNG_IMAGE_NAME}:${DOCKER_TAG}" .
if [ "$1" = "push" ]; then
docker push "${SEARXNG_IMAGE_NAME}:latest"
docker push "${SEARXNG_IMAGE_NAME}:${DOCKER_TAG}"
fi
)
dump_return $?
}
# shellcheck disable=SC2119 # shellcheck disable=SC2119
gecko.driver() { gecko.driver() {
pyenv.install pyenv.install

View file

@ -4,7 +4,7 @@ cov-core==1.15.0
black==24.3.0 black==24.3.0
pylint==3.3.7 pylint==3.3.7
splinter==0.21.0 splinter==0.21.0
selenium==4.31.0 selenium==4.32.0
Pallets-Sphinx-Themes==2.3.0 Pallets-Sphinx-Themes==2.3.0
Sphinx==7.4.7 Sphinx==7.4.7
sphinx-issues==5.0.1 sphinx-issues==5.0.1

View file

@ -1,7 +1,7 @@
certifi==2025.4.26 certifi==2025.4.26
babel==2.17.0 babel==2.17.0
flask-babel==4.0.0 flask-babel==4.0.0
flask==3.1.0 flask==3.1.1
jinja2==3.1.6 jinja2==3.1.6
lxml==5.4.0 lxml==5.4.0
pygments==2.19.1 pygments==2.19.1
@ -12,7 +12,7 @@ Brotli==1.1.0
uvloop==0.21.0 uvloop==0.21.0
httpx-socks[asyncio]==0.7.7 httpx-socks[asyncio]==0.7.7
setproctitle==1.3.6 setproctitle==1.3.6
redis==5.0.8 redis==5.2.1
markdown-it-py==3.0.0 markdown-it-py==3.0.0
fasttext-predict==0.9.2.4 fasttext-predict==0.9.2.4
tomli==2.2.1; python_version < '3.11' tomli==2.2.1; python_version < '3.11'

View file

@ -51,6 +51,9 @@ def request(query, params):
if netloc == main_wiki: if netloc == main_wiki:
eng_lang: str = traits.get_language(sxng_lang, 'English') # type: ignore eng_lang: str = traits.get_language(sxng_lang, 'English') # type: ignore
query += ' (' + eng_lang + ')' query += ' (' + eng_lang + ')'
# wiki.archlinux.org is protected by anubis
# - https://github.com/searxng/searxng/issues/4646#issuecomment-2817848019
params['headers']['User-Agent'] = "SearXNG"
elif netloc == 'wiki.archlinuxcn.org': elif netloc == 'wiki.archlinuxcn.org':
base_url = 'https://' + netloc + '/wzh/index.php?' base_url = 'https://' + netloc + '/wzh/index.php?'

View file

@ -169,18 +169,6 @@ ui:
# - image_proxy # - image_proxy
# - query_in_title # - 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 # communication with search engines
# #
outgoing: outgoing:

View file

@ -230,11 +230,6 @@ SCHEMA = {
'extra_proxy_timeout': SettingsValue(int, 0), 'extra_proxy_timeout': SettingsValue(int, 0),
'networks': {}, 'networks': {},
}, },
'result_proxy': {
'url': SettingsValue((None, str), None),
'key': SettingsBytesValue((None, bytes), None),
'proxify_results': SettingsValue(bool, False),
},
'plugins': SettingsValue(dict, {}), 'plugins': SettingsValue(dict, {}),
'checker': { 'checker': {
'off_when_debug': SettingsValue(bool, True, None), 'off_when_debug': SettingsValue(bool, True, None),

View file

@ -44,10 +44,10 @@
{%- endmacro -%} {%- endmacro -%}
<!-- Draw result sub footer --> <!-- Draw result sub footer -->
{%- macro result_sub_footer(result, proxify) -%} {%- macro result_sub_footer(result) -%}
<div class="engines"> <div class="engines">
{% for engine in result.engines %}<span>{{ engine }}</span>{% endfor %} {% for engine in result.engines %}<span>{{ engine }}</span>{% endfor %}
{{ icon_small('ellipsis-vertical') + result_link(cache_url + result.url, _('cached'), "cache_link") }}&lrm; {% if proxify and proxify_results %} {{ result_link(proxify(result.url), _('proxied'), "proxyfied_link") }} {% endif %} {{ icon_small('ellipsis-vertical') + result_link(cache_url + result.url, _('cached'), "cache_link") }}
</div>{{- '' -}} </div>{{- '' -}}
<div class="break"></div>{{- '' -}} <div class="break"></div>{{- '' -}}
{%- endmacro -%} {%- endmacro -%}

View file

@ -28,5 +28,5 @@
{{- result.codelines|code_highlighter(result.code_language)|safe -}} {{- result.codelines|code_highlighter(result.code_language)|safe -}}
</div> </div>
{{- result_sub_footer(result, proxify) -}} {{- result_sub_footer(result) -}}
{{- result_footer(result) -}} {{- result_footer(result) -}}

View file

@ -14,7 +14,7 @@
{{ _('This site did not provide any description.')|safe }} {{ _('This site did not provide any description.')|safe }}
</p> </p>
{% endif -%} {% endif -%}
{{- result_sub_footer(result, proxify) -}} {{- result_sub_footer(result) -}}
{% if result.iframe_src -%} {% if result.iframe_src -%}
<div id="result-media-{{ index }}" class="embedded-content invisible"> <div id="result-media-{{ index }}" class="embedded-content invisible">
<iframe data-src="{{result.iframe_src}}" frameborder="0" allowfullscreen></iframe> <iframe data-src="{{result.iframe_src}}" frameborder="0" allowfullscreen></iframe>

View file

@ -43,7 +43,7 @@
<small> <a class="btn-collapse collapsed searxng_init_map hide_if_nojs" data-target="#result-map-{{ index }}" data-btn-text-collapsed="{{ _('show map') }}" data-btn-text-not-collapsed="{{ _('hide map') }}" data-leaflet-target="osm-map-{{ index }}" data-map-lon="{{ result.longitude }}" data-map-lat="{{ result.latitude }}" {% if result.boundingbox %}data-map-boundingbox='{{ result.boundingbox|tojson|safe }}'{% endif %} {% if result.geojson %}data-map-geojson='{{ result.geojson|tojson|safe }}'{% endif %}>{{ icon_small( 'globe') }} {{ _('show map') }}</a></small> <small> <a class="btn-collapse collapsed searxng_init_map hide_if_nojs" data-target="#result-map-{{ index }}" data-btn-text-collapsed="{{ _('show map') }}" data-btn-text-not-collapsed="{{ _('hide map') }}" data-leaflet-target="osm-map-{{ index }}" data-map-lon="{{ result.longitude }}" data-map-lat="{{ result.latitude }}" {% if result.boundingbox %}data-map-boundingbox='{{ result.boundingbox|tojson|safe }}'{% endif %} {% if result.geojson %}data-map-geojson='{{ result.geojson|tojson|safe }}'{% endif %}>{{ icon_small( 'globe') }} {{ _('show map') }}</a></small>
{%- endif -%} {%- endif -%}
{{- result_sub_footer(result, proxify) -}} {{- result_sub_footer(result) -}}
{% if (result.latitude and result.longitude) or result.boundingbox -%} {% if (result.latitude and result.longitude) or result.boundingbox -%}
<div id="result-map-{{ index }}" class="invisible"><div id="osm-map-{{ index }}" class="osm-map-box"></div></div> <div id="result-map-{{ index }}" class="invisible"><div id="osm-map-{{ index }}" class="osm-map-box"></div></div>

View file

@ -34,5 +34,5 @@
{%- if result.html_url -%}{{ result_link(result.html_url, _('HTML')) }}{%- endif -%} {%- if result.html_url -%}{{ result_link(result.html_url, _('HTML')) }}{%- endif -%}
{%- if result.doi %}{{ result_link('https://www.altmetric.com/details/doi/' + result.doi, 'Altmetric') }}{% endif -%} {%- if result.doi %}{{ result_link('https://www.altmetric.com/details/doi/' + result.doi, 'Altmetric') }}{% endif -%}
</p> </p>
{{- result_sub_footer(result, proxify) -}} {{- result_sub_footer(result) -}}
{{- result_footer(result) }} {{- result_footer(result) }}

View file

@ -10,5 +10,5 @@
{{ result.content|safe }} {{ result.content|safe }}
</p> </p>
{% endif -%} {% endif -%}
{{- result_sub_footer(result, proxify) -}} {{- result_sub_footer(result) -}}
{{- result_footer(result) }} {{- result_footer(result) }}

View file

@ -19,5 +19,5 @@
{%- if result.files %}{{ icon_big('file') }} <span class="badge">{{ result.files }} {{ _('Number of Files') }}</span>{%- endif -%} {%- if result.files %}{{ icon_big('file') }} <span class="badge">{{ result.files }} {{ _('Number of Files') }}</span>{%- endif -%}
</p> </p>
{%- if result.content %}<p class="content">{{ result.content|safe }}</p>{%- endif -%} {%- if result.content %}<p class="content">{{ result.content|safe }}</p>{%- endif -%}
{{- result_sub_footer(result, proxify) -}} {{- result_sub_footer(result) -}}
{{- result_footer(result) -}} {{- result_footer(result) -}}

View file

@ -15,7 +15,7 @@
</p> </p>
{% endif -%} {% endif -%}
</p> </p>
{{- result_sub_footer(result, proxify) -}} {{- result_sub_footer(result) -}}
{% if result.iframe_src -%} {% if result.iframe_src -%}
<div id="result-video-{{ index }}" class="embedded-video invisible"> <div id="result-video-{{ index }}" class="embedded-video invisible">
<iframe data-src="{{result.iframe_src}}" frameborder="0" allowfullscreen></iframe> <iframe data-src="{{result.iframe_src}}" frameborder="0" allowfullscreen></iframe>

View file

@ -41,6 +41,12 @@ def subprocess_run(args, **kwargs):
def get_git_url_and_branch(): def get_git_url_and_branch():
# handle GHA directly
if "GITHUB_REPOSITORY" in os.environ and "GITHUB_REF_NAME" in os.environ:
git_url = f"https://github.com/{os.environ['GITHUB_REPOSITORY']}"
git_branch = os.environ["GITHUB_REF_NAME"]
return git_url, git_branch
try: try:
ref = subprocess_run("git rev-parse --abbrev-ref @{upstream}") ref = subprocess_run("git rev-parse --abbrev-ref @{upstream}")
except subprocess.CalledProcessError: except subprocess.CalledProcessError:

View file

@ -7,8 +7,6 @@
from __future__ import annotations from __future__ import annotations
import inspect import inspect
import hashlib
import hmac
import json import json
import os import os
import sys import sys
@ -261,24 +259,6 @@ def custom_url_for(endpoint: str, **values):
return url_for(endpoint, **values) + suffix return url_for(endpoint, **values) + suffix
def morty_proxify(url: str):
if not url:
return url
if url.startswith('//'):
url = 'https:' + url
if not settings['result_proxy']['url']:
return url
url_params = dict(mortyurl=url)
if settings['result_proxy']['key']:
url_params['mortyhash'] = hmac.new(settings['result_proxy']['key'], url.encode(), hashlib.sha256).hexdigest()
return '{0}?{1}'.format(settings['result_proxy']['url'], urlencode(url_params))
def image_proxify(url: str): def image_proxify(url: str):
if not url: if not url:
return url return url
@ -300,9 +280,6 @@ def image_proxify(url: str):
return url return url
return None return None
if settings['result_proxy']['url']:
return morty_proxify(url)
h = new_hmac(settings['server']['secret_key'], url.encode()) h = new_hmac(settings['server']['secret_key'], url.encode())
return '{0}?{1}'.format(url_for('image_proxy'), urlencode(dict(url=url.encode(), h=h))) return '{0}?{1}'.format(url_for('image_proxy'), urlencode(dict(url=url.encode(), h=h)))
@ -424,8 +401,6 @@ def render(template_name: str, **kwargs):
kwargs['url_for'] = custom_url_for # override url_for function in templates kwargs['url_for'] = custom_url_for # override url_for function in templates
kwargs['image_proxify'] = image_proxify kwargs['image_proxify'] = image_proxify
kwargs['favicon_url'] = favicons.favicon_url kwargs['favicon_url'] = favicons.favicon_url
kwargs['proxify'] = morty_proxify if settings['result_proxy']['url'] is not None else None
kwargs['proxify_results'] = settings['result_proxy']['proxify_results']
kwargs['cache_url'] = settings['ui']['cache_url'] kwargs['cache_url'] = settings['ui']['cache_url']
kwargs['get_result_template'] = get_result_template kwargs['get_result_template'] = get_result_template
kwargs['opensearch_url'] = ( kwargs['opensearch_url'] = (

View file

@ -4,6 +4,3 @@ server:
bind_address: "[::]" bind_address: "[::]"
default_http_headers: default_http_headers:
Custom-Header: Custom-Value Custom-Header: Custom-Value
result_proxy:
url: https://localhost/morty
key: "$ecretKey"

View file

@ -1,125 +0,0 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: AGPL-3.0-or-later
# shellcheck disable=SC2001
# shellcheck source=utils/lib.sh
source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
# ----------------------------------------------------------------------------
# config
# ----------------------------------------------------------------------------
PUBLIC_URL="${PUBLIC_URL:-${SEARXNG_URL}}"
FILTRON_ETC="/etc/filtron"
SERVICE_NAME="filtron"
SERVICE_USER="${SERVICE_USER:-${SERVICE_NAME}}"
SERVICE_SYSTEMD_UNIT="${SYSTEMD_UNITS}/${SERVICE_NAME}.service"
APACHE_FILTRON_SITE="searx.conf"
NGINX_FILTRON_SITE="searx.conf"
# ----------------------------------------------------------------------------
usage() {
# ----------------------------------------------------------------------------
# shellcheck disable=SC1117
cat <<EOF
usage::
$(basename "$0") remove all
$(basename "$0") apache remove
$(basename "$0") nginx remove
remove all : drop all components of the filtron service
apache remove : drop apache site ${APACHE_FILTRON_SITE}
nginx remove : drop nginx site ${NGINX_FILTRON_SITE}
environment:
PUBLIC_URL : ${PUBLIC_URL}
EOF
[[ -n ${1} ]] && err_msg "$1"
}
main() {
local _usage="unknown or missing $1 command $2"
case $1 in
-h|--help) usage; exit 0;;
remove)
sudo_or_exit
case $2 in
all) remove_all;;
*) usage "$_usage"; exit 42;;
esac ;;
apache)
sudo_or_exit
case $2 in
remove) remove_apache_site ;;
*) usage "$_usage"; exit 42;;
esac ;;
nginx)
sudo_or_exit
case $2 in
remove) remove_nginx_site ;;
*) usage "$_usage"; exit 42;;
esac ;;
*) usage "unknown or missing command $1"; exit 42;;
esac
}
remove_all() {
rst_title "De-Install $SERVICE_NAME (service)"
rst_para "\
It goes without saying that this script can only be used to remove
installations that were installed with this script."
if ! systemd_remove_service "${SERVICE_NAME}" "${SERVICE_SYSTEMD_UNIT}"; then
return 42
fi
drop_service_account "${SERVICE_USER}"
rm -r "$FILTRON_ETC" 2>&1 | prefix_stdout
if service_is_available "${PUBLIC_URL}"; then
MSG="** Don't forget to remove your public site! (${PUBLIC_URL}) **" wait_key 10
fi
}
remove_apache_site() {
rst_title "Remove Apache site $APACHE_FILTRON_SITE"
rst_para "\
This removes apache site ${APACHE_FILTRON_SITE}."
! apache_is_installed && err_msg "Apache is not installed."
if ! ask_yn "Do you really want to continue?" Yn; then
return
fi
apache_remove_site "$APACHE_FILTRON_SITE"
}
remove_nginx_site() {
rst_title "Remove nginx site $NGINX_FILTRON_SITE"
rst_para "\
This removes nginx site ${NGINX_FILTRON_SITE}."
! nginx_is_installed && err_msg "nginx is not installed."
if ! ask_yn "Do you really want to continue?" Yn; then
return
fi
nginx_remove_app "$FILTRON_FILTRON_SITE"
}
# ----------------------------------------------------------------------------
main "$@"
# ----------------------------------------------------------------------------

View file

@ -1802,8 +1802,8 @@ url_replace_hostname(){
# to replace hostname by primary IP:: # to replace hostname by primary IP::
# #
# url_replace_hostname http://searx-ubu1604/morty $(primary_ip) # url_replace_hostname http://searx-ubu1604/example $(primary_ip)
# http://10.246.86.250/morty # http://10.246.86.250/example
# shellcheck disable=SC2001 # shellcheck disable=SC2001
echo "$1" | sed "s|\(http[s]*://\)[^/]*\(.*\)|\1$2\2|" echo "$1" | sed "s|\(http[s]*://\)[^/]*\(.*\)|\1$2\2|"

306
utils/lib_sxng_container.sh Normal file
View file

@ -0,0 +1,306 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: AGPL-3.0-or-later
container.help() {
cat <<EOF
container.:
build : build container image
EOF
}
CONTAINER_IMAGE_ORGANIZATION=${GITHUB_REPOSITORY_OWNER:-"searxng"}
CONTAINER_IMAGE_NAME="searxng"
container.build() {
local parch=${OVERRIDE_ARCH:-$(uname -m)}
local container_engine
local dockerfile
local arch
local variant
local platform
required_commands git
# Check if podman or docker is installed
if [ "$1" = "podman" ] || [ "$1" = "docker" ]; then
if ! command -v "$1" &>/dev/null; then
die 42 "$1 is not installed"
fi
container_engine="$1"
else
# If no explicit engine is passed, prioritize podman over docker
if command -v podman &>/dev/null; then
container_engine="podman"
elif command -v docker &>/dev/null; then
container_engine="docker"
else
die 42 "no compatible container engine is installed (podman or docker)"
fi
fi
info_msg "Selected engine: $container_engine"
# Setup arch specific
case $parch in
"X64" | "x86_64" | "amd64")
dockerfile="Dockerfile"
arch="amd64"
variant=""
platform="linux/$arch"
;;
"ARM64" | "aarch64" | "arm64")
dockerfile="Dockerfile"
arch="arm64"
variant=""
platform="linux/$arch"
;;
"ARMV7" | "armhf" | "armv7l" | "armv7")
dockerfile="legacy/Dockerfile"
arch="arm"
variant="v7"
platform="linux/$arch/$variant"
;;
*)
err_msg "Unsupported architecture; $parch"
exit 1
;;
esac
info_msg "Selected platform: $platform"
pyenv.install
(
set -e
pyenv.activate
# Check if it is a git repository
if [ ! -d .git ]; then
die 1 "This is not Git repository"
fi
if ! git remote get-url origin &>/dev/null; then
die 1 "There is no remote origin"
fi
# This is a git repository
git update-index -q --refresh
python -m searx.version freeze
eval "$(python -m searx.version)"
info_msg "Set \$VERSION_STRING: $VERSION_STRING"
info_msg "Set \$VERSION_TAG: $VERSION_TAG"
info_msg "Set \$DOCKER_TAG: $DOCKER_TAG"
info_msg "Set \$GIT_URL: $GIT_URL"
info_msg "Set \$GIT_BRANCH: $GIT_BRANCH"
if [ "$container_engine" = "podman" ]; then
params_build_builder="build --format=docker --platform=$platform --target=builder --layers --identity-label=false"
params_build="build --format=docker --platform=$platform --layers --squash-all --omit-history --identity-label=false"
else
params_build_builder="build --platform=$platform --target=builder"
params_build="build --platform=$platform --squash"
fi
if [ "$GITHUB_ACTIONS" = "true" ]; then
params_build_builder+=" --cache-from=ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache --cache-to=ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache"
# Tags
params_build+=" --tag=ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache:$CONTAINER_IMAGE_NAME-$arch$variant"
else
# Tags
params_build+=" --tag=localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:latest"
params_build+=" --tag=localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:$DOCKER_TAG"
fi
# shellcheck disable=SC2086
"$container_engine" $params_build_builder \
--build-arg="TIMESTAMP_SETTINGS=$(git log -1 --format="%cd" --date=unix -- ./searx/settings.yml)" \
--build-arg="TIMESTAMP_UWSGI=$(git log -1 --format="%cd" --date=unix -- ./container/uwsgi.ini)" \
--tag="localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:builder" \
--file="./container/$dockerfile" \
.
build_msg CONTAINER "Image \"builder\" built"
# shellcheck disable=SC2086
"$container_engine" $params_build \
--build-arg="GIT_URL=$GIT_URL" \
--build-arg="SEARXNG_GIT_VERSION=$VERSION_STRING" \
--build-arg="LABEL_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--build-arg="LABEL_VCS_REF=$(git rev-parse HEAD)" \
--build-arg="LABEL_VCS_URL=$GIT_URL" \
--file="./container/$dockerfile" \
.
build_msg CONTAINER "Image built"
if [ "$GITHUB_ACTIONS" = "true" ]; then
"$container_engine" push "ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache:$CONTAINER_IMAGE_NAME-$arch$variant"
# Output to GHA
cat <<EOF >>"$GITHUB_OUTPUT"
version_string=$VERSION_STRING
version_tag=$VERSION_TAG
docker_tag=$DOCKER_TAG
git_url=$GIT_URL
git_branch=$GIT_BRANCH
EOF
fi
)
dump_return $?
}
container.test() {
local parch=${OVERRIDE_ARCH:-$(uname -m)}
local arch
local variant
local platform
if [ "$GITHUB_ACTIONS" != "true" ]; then
die 1 "This command is intended to be run in GitHub Actions"
fi
required_commands podman
# Setup arch specific
case $parch in
"X64" | "x86_64" | "amd64")
arch="amd64"
variant=""
platform="linux/$arch"
;;
"ARM64" | "aarch64" | "arm64")
arch="arm64"
variant=""
platform="linux/$arch"
;;
"ARMV7" | "armhf" | "armv7l" | "armv7")
arch="arm"
variant="v7"
platform="linux/$arch/$variant"
;;
*)
err_msg "Unsupported architecture; $parch"
exit 1
;;
esac
build_msg CONTAINER "Selected platform: $platform"
(
set -e
podman pull "ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache:$CONTAINER_IMAGE_NAME-$arch$variant"
name="$CONTAINER_IMAGE_NAME-$(date +%N)"
podman create --name="$name" --rm --timeout=60 --network="host" \
"ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache:$CONTAINER_IMAGE_NAME-$arch$variant" >/dev/null
podman start "$name" >/dev/null
podman logs -f "$name" &
pid_logs=$!
# Wait until container is ready
sleep 5
curl -vf --max-time 5 "http://localhost:8080/healthz"
kill $pid_logs &>/dev/null || true
podman stop "$name" >/dev/null
)
dump_return $?
}
container.push() {
# Architectures on manifest
local release_archs=("amd64" "arm64" "armv7")
local archs=()
local variants=()
local platforms=()
if [ "$GITHUB_ACTIONS" != "true" ]; then
die 1 "This command is intended to be run in GitHub Actions"
fi
required_commands podman
for arch in "${release_archs[@]}"; do
case $arch in
"X64" | "x86_64" | "amd64")
archs+=("amd64")
variants+=("")
platforms+=("linux/${archs[-1]}")
;;
"ARM64" | "aarch64" | "arm64")
archs+=("arm64")
variants+=("")
platforms+=("linux/${archs[-1]}")
;;
"ARMV7" | "armv7" | "armhf" | "arm")
archs+=("arm")
variants+=("v7")
platforms+=("linux/${archs[-1]}/${variants[-1]}")
;;
*)
err_msg "Unsupported architecture; $arch"
exit 1
;;
esac
done
(
set -e
# Pull archs
for i in "${!archs[@]}"; do
podman pull "ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache:$CONTAINER_IMAGE_NAME-${archs[$i]}${variants[$i]}"
done
# Manifest tags
release_tags=("latest" "$DOCKER_TAG")
# Create manifests
for tag in "${release_tags[@]}"; do
if ! podman manifest exists "localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:$tag"; then
podman manifest create "localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:$tag"
fi
# Add archs to manifest
for i in "${!archs[@]}"; do
podman manifest add \
"localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:$tag" \
"containers-storage:ghcr.io/$CONTAINER_IMAGE_ORGANIZATION/cache:$CONTAINER_IMAGE_NAME-${archs[$i]}${variants[$i]}"
done
done
podman image list
# Remote registries
release_registries=("ghcr.io" "docker.io")
# Push manifests
for registry in "${release_registries[@]}"; do
for tag in "${release_tags[@]}"; do
build_msg CONTAINER "Pushing manifest $tag to $registry"
podman manifest push \
"localhost/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:$tag" \
"docker://$registry/$CONTAINER_IMAGE_ORGANIZATION/$CONTAINER_IMAGE_NAME:$tag"
done
done
)
dump_return $?
}
# Alias
podman.build() {
container.build podman
}
# Alias
docker.build() {
container.build docker
}
# Alias
docker.buildx() {
container.build docker
}

View file

@ -1,124 +0,0 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: AGPL-3.0-or-later
# shellcheck source=utils/lib.sh
source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
# ----------------------------------------------------------------------------
# config
# ----------------------------------------------------------------------------
PUBLIC_URL="${PUBLIC_URL:-${SEARXNG_URL}}"
MORTY_LISTEN="${MORTY_LISTEN:-127.0.0.1:3000}"
PUBLIC_URL_PATH_MORTY="${PUBLIC_URL_PATH_MORTY:-/morty/}"
PUBLIC_URL_MORTY="${PUBLIC_URL_MORTY:-$(echo "$PUBLIC_URL" | sed -e's,^\(.*://[^/]*\).*,\1,g')${PUBLIC_URL_PATH_MORTY}}"
SERVICE_NAME="morty"
SERVICE_USER="${SERVICE_USER:-${SERVICE_NAME}}"
SERVICE_SYSTEMD_UNIT="${SYSTEMD_UNITS}/${SERVICE_NAME}.service"
# Apache Settings
APACHE_MORTY_SITE="morty.conf"
NGINX_MORTY_SITE="morty.conf"
# ----------------------------------------------------------------------------
usage() {
# ----------------------------------------------------------------------------
# shellcheck disable=SC1117
cat <<EOF
usage::
$(basename "$0") remove all
$(basename "$0") apache remove
$(basename "$0") nginx remove
remove all : drop all components of the morty service
apache remove : drop apache site ${APACHE_MORTY_SITE}
nginx remove : drop nginx site ${NGINX_MORTY_SITE}
environment:
PUBLIC_URL_MORTY : ${PUBLIC_URL_MORTY}
EOF
[[ -n ${1} ]] && err_msg "$1"
}
main() {
local _usage="ERROR: unknown or missing $1 command $2"
case $1 in
-h|--help) usage; exit 0;;
remove)
sudo_or_exit
case $2 in
all) remove_all;;
*) usage "$_usage"; exit 42;;
esac ;;
apache)
sudo_or_exit
case $2 in
remove) remove_apache_site ;;
*) usage "$_usage"; exit 42;;
esac ;;
nginx)
sudo_or_exit
case $2 in
remove) remove_nginx_site ;;
*) usage "$_usage"; exit 42;;
esac ;;
*) usage "ERROR: unknown or missing command $1"; exit 42;;
esac
}
remove_all() {
rst_title "De-Install $SERVICE_NAME (service)"
rst_para "\
It goes without saying that this script can only be used to remove
installations that were installed with this script."
if systemd_remove_service "${SERVICE_NAME}" "${SERVICE_SYSTEMD_UNIT}"; then
drop_service_account "${SERVICE_USER}"
fi
}
remove_apache_site() {
rst_title "Remove Apache site $APACHE_MORTY_SITE"
rst_para "\
This removes apache site ${APACHE_MORTY_SITE}."
! apache_is_installed && err_msg "Apache is not installed."
if ! ask_yn "Do you really want to continue?" Yn; then
return
fi
apache_remove_site "$APACHE_MORTY_SITE"
}
remove_nginx_site() {
rst_title "Remove nginx site $NGINX_MORTY_SITE"
rst_para "\
This removes nginx site ${NGINX_MORTY_SITE}."
! nginx_is_installed && err_msg "nginx is not installed."
if ! ask_yn "Do you really want to continue?" Yn; then
return
fi
nginx_remove_app "$NGINX_MORTY_SITE"
}
# ----------------------------------------------------------------------------
main "$@"
# ----------------------------------------------------------------------------

View file

@ -1,88 +0,0 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: AGPL-3.0-or-later
# shellcheck disable=SC2001
# shellcheck source=utils/lib.sh
source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
# ----------------------------------------------------------------------------
# config
# ----------------------------------------------------------------------------
PUBLIC_URL="${PUBLIC_URL:-${SEARXNG_URL}}"
SERVICE_NAME="searx"
SERVICE_USER="${SERVICE_USER:-${SERVICE_NAME}}"
SEARXNG_SETTINGS_PATH="/etc/searx/settings.yml"
SEARXNG_UWSGI_APP="searx.ini"
# ----------------------------------------------------------------------------
usage() {
# ----------------------------------------------------------------------------
# shellcheck disable=SC1117
cat <<EOF
usage::
$(basename "$0") remove all
remove all: complete uninstall of SearXNG service
environment:
PUBLIC_URL : ${PUBLIC_URL}
EOF
[[ -n ${1} ]] && err_msg "$1"
}
main() {
local _usage="unknown or missing $1 command $2"
case $1 in
remove)
rst_title "SearXNG (remove)" part
sudo_or_exit
case $2 in
all) remove_all;;
*) usage "$_usage"; exit 42;;
esac ;;
*) usage "unknown or missing command $1"; exit 42;;
esac
}
remove_all() {
rst_title "De-Install SearXNG (service)"
rst_para "\
It goes without saying that this script can only be used to remove
installations that were installed with this script."
if ! ask_yn "Do you really want to deinstall SearXNG?"; then
return
fi
remove_searx_uwsgi
drop_service_account "${SERVICE_USER}"
remove_settings
wait_key
if service_is_available "${PUBLIC_URL}"; then
MSG="** Don't forget to remove your public site! (${PUBLIC_URL}) **" wait_key 10
fi
}
remove_settings() {
rst_title "remove SearXNG settings" section
echo
info_msg "delete ${SEARXNG_SETTINGS_PATH}"
rm -f "${SEARXNG_SETTINGS_PATH}"
}
remove_searx_uwsgi() {
rst_title "Remove SearXNG's uWSGI app (searxng.ini)" section
echo
uWSGI_remove_app "$SEARXNG_UWSGI_APP"
}
# ----------------------------------------------------------------------------
main "$@"
# ----------------------------------------------------------------------------

View file

@ -553,15 +553,6 @@ searxng.remove.settings() {
searxng.check() { searxng.check() {
rst_title "SearXNG checks" section rst_title "SearXNG checks" section
for NAME in "searx" "filtron" "morty"; do
if service_account_is_available "${NAME}"; then
err_msg "There exists an old '${NAME}' account from a previous installation."
else
info_msg "[OK] (old) account '${NAME}' does not exists"
fi
done
"${SEARXNG_PYENV}/bin/python" "${SEARXNG_SRC}/utils/searxng_check.py" "${SEARXNG_PYENV}/bin/python" "${SEARXNG_SRC}/utils/searxng_check.py"
} }

View file

@ -1,29 +0,0 @@
[Unit]
Description=${SERVICE_NAME}
After=syslog.target
After=network.target
[Service]
Type=simple
User=${SERVICE_USER}
Group=${SERVICE_GROUP}
WorkingDirectory=${SERVICE_HOME}
ExecStart=${SERVICE_HOME}/go-apps/bin/filtron -api '${FILTRON_API}' -listen '${FILTRON_LISTEN}' -rules '${FILTRON_RULES}' -target '${FILTRON_TARGET}'
Restart=always
Environment=USER=${SERVICE_USER} HOME=${SERVICE_HOME}
# Some distributions may not support these hardening directives. If you cannot
# start the service due to an unknown option, comment out the ones not supported
# by your version of systemd.
ProtectSystem=full
PrivateDevices=yes
PrivateTmp=yes
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target

View file

@ -1,29 +0,0 @@
[Unit]
Description=${SERVICE_NAME}
After=syslog.target
After=network.target
[Service]
Type=simple
User=${SERVICE_USER}
Group=${SERVICE_GROUP}
WorkingDirectory=${SERVICE_HOME}
ExecStart=${SERVICE_HOME}/go-apps/bin/morty -key '${MORTY_KEY}' -listen '${MORTY_LISTEN}' -timeout ${MORTY_TIMEOUT}
Restart=always
Environment=USER=${SERVICE_USER} HOME=${SERVICE_HOME} DEBUG=${SERVICE_ENV_DEBUG}
# Some distributions may not support these hardening directives. If you cannot
# start the service due to an unknown option, comment out the ones not supported
# by your version of systemd.
ProtectSystem=full
PrivateDevices=yes
PrivateTmp=yes
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target