Hosting Searxng on Alpine

2023-07-25

Here’s how you could host Searxng on Alpine Linux.

Note that I don’t wish to create a venv.

[ $(id -u) -eq 0 ] || exit 1

apk add git python3 py3-gunicorn py3-pip py3-yaml

mkdir /usr/local/searx
addgroup -S searx
adduser -S -D -h /usr/local/searx -s /sbin/nologin -G searx searx
chown -R searx:searx /usr/local/searx
doas -u searx git clone https://github.com/searxng/searxng.git /usr/local/searx/searx-src
doas -u searx pip install -r /usr/local/searx/searx-src/requirements.txt

Follow the official guide for the /etc/searxng/settings.yml stuff and then try to run.

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

Hope to see something like this:

/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
[2023-07-25 21:40:38 +0000] [2837] [INFO] Starting gunicorn 20.1.0
[2023-07-25 21:40:38 +0000] [2837] [INFO] Listening at: http://127.0.0.1:8001 (2837)
[2023-07-25 21:40:38 +0000] [2837] [INFO] Using worker: sync
[2023-07-25 21:40:38 +0000] [2838] [INFO] Booting worker with pid: 2838

Now you got searxng running but if you want it public we should prepare filtron and morty, and make them services. 🥵

doas apk add go
go install github.com/asciimoo/filtron@latest
go install github.com/asciimoo/morty@latest
doas mv ~/go/bin/filtron ~/go/bin/morty /usr/local/bin

doas addgroup -S filtron
doas adduser -S -D -H -s /sbin/nologin -G filtron filtron
doas addgroup -S morty
doas adduser -S -D -H -s /sbin/nologin -G morty morty

Now, let me omit obvious explainations. The point is you should get to have something like this:

searx:~$ cat /etc/init.d/filtron
#!/sbin/openrc-run

supervisor=supervise-daemon
name=filtron
command="/usr/local/bin/filtron"
command_args="-api '127.0.0.1:4005' -listen '127.0.0.1:4004' -rules '/etc/filtron/rules.json' -target '127.0.0.1:8001'"
command_user="${FILTRON_USER:-filtron}"
pidfile="/run/filtron.pid"

depend() {
  need net
  after firewall
}
searx:~$ doas rc-service filtron start
 * Starting filtron ...                                                    [ ok ]
searx:~$ doas rc-update add filtron
 * service filtron added to runlevel default
searx:~$ cat /etc/init.d/morty
#!/sbin/openrc-run

supervisor=supervise-daemon
name=morty
command="/usr/local/bin/morty"
command_user="${FILTRON_USER:-morty}"
supervise_daemon_args="--env DEBUG=false --env MORTY_ADDRESS=127.0.0.1:3000 --env MORTY_KEY=<your secret key generated with `openssl rand -base64 33`>"
pidfile="/run/morty.pid"

depend() {
  need net
  after firewall
}
searx:~$ doas rc-service morty start
 * Starting morty ...                                                      [ ok ]
searx:~$ doas rc-update add morty
 * service morty added to runlevel default
searx:~$ cat /etc/init.d/searx
#!/sbin/openrc-run

supervisor=supervise-daemon
name=searx
command="/usr/bin/gunicorn"
command_args="-b 127.0.0.1:8001 --chdir /usr/local/searx/searx-src/searx --pythonpath /usr/local/searx/searx-src searx.webapp"
command_user="${SEARX_USER:-searx}"
pidfile="/run/searx.pid"

depend() {
  need net
  after firewall
}
searx:~$ doas rc-service searx start
 * Caching service dependencies ...                                                                        [ ok ]
 * Starting searx ...                                                                                      [ ok ]
searx:~$ doas rc-update add searx
 * service searx added to runlevel default

Got it?

searx:~$ doas netstat -ltp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 searx.searx.fmac.xyz:8001 0.0.0.0:*               LISTEN      4526/gunicorn: mast
tcp        0      0 searx.searx.fmac.xyz:4005 0.0.0.0:*               LISTEN      4337/filtron
tcp        0      0 searx.searx.fmac.xyz:4004 0.0.0.0:*               LISTEN      4337/filtron
tcp        0      0 searx.searx.fmac.xyz:3000 0.0.0.0:*               LISTEN      4367/morty

Cool. We can now serve this through a nice reverse proxy.

doas apk add caddy
searx:~$ cat /etc/caddy/Caddyfile
# Refer to the Caddy docs for more information:
# https://caddyserver.com/docs/caddyfile

searx.fmac.xyz {
	tls {
		protocols tls1.2 tls1.3
		ciphers TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
	}

	root * /usr/local/searx/searx-src/searx

	@static {
		method GET
		path /static/*
	}
	file_server @static

	@searx {
		not path /static/*
		not path /morty/*
	}
	reverse_proxy @searx 127.0.0.1:4004 {
		header_up X-Real-IP {http.request.remote.host}
	}

	reverse_proxy /morty/* 127.0.0.1:3000 {
		header_up Host {http.reverse_proxy.upstream.hostport}
		header_up X-Real-IP {http.request.remote.host}
	}

	header * Strict-Transport-Security "max-age=63072000"
	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'"
	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 * 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"
	header * X-Frame-Options "SAMEORIGIN"
	header * -Server

	encode zstd gzip

	log {
		output file /var/log/caddy/searx.fmac.xyz.access.log {
			roll_size 1gb
			roll_keep 12
			roll_keep_for 48h
		}
		level error
	}
}
searx:~$ doas rc-service caddy start
searx:~$ doas rc-update add caddy

Enjoy c: