Files
Курнат Андрей e48e1e36a5
Android / test-and-build (push) Canceled after 0s
Server / deployment-config (push) Canceled after 0s
Server / vulnerability-scan (push) Canceled after 0s
Implement background media ingestion and Pi deployment
2026-07-15 22:58:03 +03:00

97 lines
3.2 KiB
Markdown

# Raspberry Pi deployment
This profile runs the single-container QSfera server on a 64-bit Raspberry Pi
OS and persists configuration and user data outside the container. It expects a
separate reverse proxy for a browser-trusted TLS certificate; by default port
9200 is therefore published only on `127.0.0.1`.
## Requirements
- `uname -m` must report `aarch64` or `arm64`.
- Docker Engine with the Compose plugin must be installed.
- The selected QSfera image tag or digest must contain `linux/arm64`.
- The configuration and data directories must be on persistent storage and
writable by UID/GID `1000:1000`, which is the non-root user in the image.
For an external disk mounted at `/mnt/qsfera`, create the directories with:
```sh
sudo install -d -o 1000 -g 1000 -m 0750 /mnt/qsfera/config /mnt/qsfera/data
findmnt /mnt/qsfera
```
`findmnt` must show the expected external filesystem before the service starts.
This prevents an unavailable disk from silently placing data on the Pi's root
filesystem.
## Configuration
```sh
cd Server/deployments/raspberry-pi
cp .env.example .env
chmod 600 .env
```
Fill every empty value in `.env`. The Compose file deliberately has no default
for the image, public URL, admin password, persistent paths or memory limit.
`docker compose config` fails when any of these values is empty.
Choose `QSFERA_MEMORY_LIMIT` from measurements on the target Pi:
```text
QSFERA_MEMORY_LIMIT = total RAM - OS reserve - other services reserve
```
Use `free -h` for total/current host memory and `docker stats` for the other
containers. Leave enough headroom for the kernel, filesystem cache and reverse
proxy. QSfera's Go runtime then derives its own default `GOMEMLIMIT` from the
container limit with a 0.9 ratio.
Keep `QSFERA_BIND_IP=127.0.0.1` when the reverse proxy runs on the same Pi. Set
it to a reachable interface only when access to port 9200 is protected by an
equivalent network and TLS design.
## Start and verify
```sh
sh ./smoke-test.sh
docker compose ps
```
The smoke test validates the Compose file, starts the service and waits for the
container health check. Its default 180-second startup budget can be changed
with `SMOKE_TIMEOUT_SECONDS`.
## Backup
The backup script stops QSfera, archives both persistent directories, writes a
SHA-256 checksum and starts the service again:
```sh
sh ./backup.sh /mnt/backups/qsfera
```
Copy the resulting `.tar.gz` and `.sha256` files to storage that is independent
of the Pi and its data disk.
## Restore
Restore replaces the current configuration and data. Check the selected archive
and its checksum first, then run:
```sh
RESTORE_CONFIRM=restore sh ./restore.sh /mnt/backups/qsfera/qsfera-TIMESTAMP.tar.gz
sh ./smoke-test.sh
```
The restore script verifies the checksum when the matching `.sha256` file is
present and stops the service during replacement. It starts QSfera only after a
successful extraction; after an error the service remains stopped so a partial
data set is never served automatically.
## References
- [Raspberry Pi external storage documentation](https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#external-storage)
- [Docker Compose service configuration](https://docs.docker.com/reference/compose-file/services/)
- [Go garbage collector guide](https://go.dev/doc/gc-guide)