Hosting a Searx instance on OpenBSD
2021.2.4-2021.2.6
!!!:
This post comes from my personal notes archive, so it may be confusional and/or not structured as a lesson.
Env
- OpenBSD 6.8 GENERIC#4 amd64
🐡 Installation went smooth as always…
I’ve edited the default disk layout like this:
# df -h
Filesystem Size Used Avail Capacity Mounted on
/dev/sd0a 565M 85.0M 452M 16% /
/dev/sd0k 986M 2.0K 937M 0% /home
/dev/sd0d 782M 10.0K 743M 0% /tmp
/dev/sd0f 2.9G 1.0G 1.7G 38% /usr
/dev/sd0g 619M 234M 354M 40% /usr/X11R6
/dev/sd0h 6.9G 218K 6.5G 0% /usr/local
/dev/sd0e 4.8G 6.9M 4.6G 0% /var
It’s considered bad to delete some of the proposed partitions but this is an experimental install.
NOTE:
I’m following https://searx.github.io/searx/admin/installation-searx.html.
Searx & gunicorn
The Searx installation guide employs
uWSGI. I don’t wanna compile uWSGI plugins for OpenBSD at the moment, so to avoid errors like
!!! UNABLE to load uWSGI plugin: File not found !!!
I’ll install gunicorn instead and improvise.
pkg_add python py3-pip git
ln -s /usr/local/bin/python3.8 /usr/local/bin/python
ln -s /usr/local/bin/pip3.8 /usr/local/bin/pip
pip install gunicorn
Create user _searx that is going to own the gunicorn process.
mkdir /usr/local/searx
useradd -d /usr/local/searx/ -s /sbin/nologin -u 10000 _searx
chown -R _searx:_searx /usr/local/searx/
NOTE:
I don’t want to use a Python virtual env for now.
cat /etc/doas.conf
permit setenv { -ENV PS1=$DOAS_PS1 SSH_AUTH_SOCK } :wheel
doas -u _searx git clone "https://github.com/searx/searx.git" \
"/usr/local/searx/searx-src"
pip install -r /usr/local/searx/searx-src/requirements.txt
if
Error: Please make sure the libxml2 and libxslt development packages are installed.
then
pkg_add py3-lxml
fi
Follow the guide for the /etc/searx/settings.yml
stuff.
Ok. Try.
cd /usr/local/searx/
doas -u _searx gunicorn -b 127.0.0.1:8001 --chdir /usr/local/searx/searx-src/searx --pythonpath /usr/local/searx/searx-src searx.webapp
[INFO] Listening at: http://127.0.0.1:8001 (93345)
Nice. Daemonize gunicorn. Create /etc/rc.d/gunisearx
.
#!/bin/ksh
RUN_DIR="/var/run/gunisearx"
daemon="/usr/local/bin/gunicorn"
gunisearx_flags="-b 127.0.0.1:8001 --chdir /usr/local/searx/searx-src/searx --pythonpath /usr/local/searx/searx-src -p /var/run/gunisearx/gunisearx.pid -D searx.webapp"
gunisearx_user="_searx"
. /etc/rc.d/rc.subr
pexp="/usr/local/bin/python.*${pexp}"
# For the PID file.
rc_pre() {
if [[ ! -d /var/run/gunisearx ]]; then
mkdir $RUN_DIR
chown -R _searx:_searx $RUN_DIR
fi
}
rc_stop() {
if [[ -f $RUN_DIR/gunisearx.pid ]]; then
kill $(cat $RUN_DIR/gunisearx.pid)
rm $RUN_DIR/gunisearx.pid
fi
}
rc_cmd $1
Filtron
Compiled filtron on a build VM and copied to the server.
Create user _filtron that is going to own the filtron process.
useradd -s /sbin/nologin -u 10001 _filtron
Daemonize filtron. Create /etc/rc.d/filtron
.
#!/bin/ksh
daemon="/usr/local/bin/filtron"
filtron_flags="-api '127.0.0.1:4005' -listen '127.0.0.1:4004' -rules '/etc/filtron/rules.json' -target '127.0.0.1:8001'"
filtron_user="_filtron"
rc_bg=YES
. /etc/rc.d/rc.subr
rc_cmd $1
morty
Compiled morty on a build VM and copied to the server.
Create user _morty that is going to own the morty process.
useradd -s /sbin/nologin -u 10002 _morty
Daemonize morty. Create /etc/rc.d/morty
.
#!/bin/ksh
daemon="/usr/local/bin/morty"
morty_user="_morty"
rc_bg=YES
. /etc/rc.d/rc.subr
rc_cmd $1
Create a login class in /etc/login.conf
to set some environment variables:
...other things...
morty:\
:setenv=DEBUG=false,MORTY_ADDRESS=127.0.0.1\c3000,MORTY_KEY=<key generated with `openssl rand -base64 33`>:\
:tc=daemon:
Bonus - nginx config
Nginx as reverse proxy and scores A+ at SSL Labs and observatory.mozilla.org.
/etc/nginx/nginx.conf
http {
...lots of things...
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name searx.fmac.xyz;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;
ssl_certificate /etc/ssl/searx.fmac.xyz.fullchain.pem;
ssl_certificate_key /etc/ssl/private/searx.fmac.xyz.key;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
location / {
proxy_pass http://127.0.0.1:4004/;
include /etc/nginx/searx-proxy-headers.conf;
include /etc/nginx/searx-default-headers.conf;
add_header Content-Security-Policy "upgrade-insecure-requests; default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; form-action 'self'; font-src 'self'; frame-ancestors 'self'; base-uri 'self'; connect-src 'self' https://overpass-api.de; img-src 'self' data: https://*.tile.openstreetmap.org; frame-src https://www.youtube-nocookie.com https://player.vimeo.com https://www.dailymotion.com https://www.deezer.com https://www.mixcloud.com https://w.soundcloud.com https://embed.spotify.com" always;
}
location /static/ {
root /var/www/htdocs/searx/;
include /etc/nginx/searx-default-headers.conf;
add_header Cache-Control "public, max-age=31536000" always;
}
location /morty {
proxy_pass http://127.0.0.1:3000/;
include /etc/nginx/searx-proxy-headers.conf;
}
}
}
/etc/nginx/searx-default-headers.conf
add_header Feature-Policy "accelerometer 'none';ambient-light-sensor 'none'; autoplay 'none';camera 'none';encrypted-media 'none';focus-without-user-activation 'none'; geolocation 'none';gyroscope 'none';magnetometer 'none';microphone 'none';midi 'none';payment 'none';picture-in-picture 'none'; speaker 'none';sync-xhr 'none';usb 'none';vr 'none'" always;
add_header Referrer-Policy "no-referrer" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Robots-Tag "noindex, noarchive, nofollow" always;
add_header X-XSS-Protection "1" always;
/etc/nginx/searx-proxy-headers.conf
proxy_hide_header Referrer-Policy;
proxy_hide_header X-Content-Type-Options;
proxy_hide_header X-Robots-Tag;
proxy_hide_header X-Xss-Protection;
proxy_set_header Host $host;
proxy_set_header Connection $http_connection;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Scheme $scheme;