---
url: /install/linux.md
---

# Linux (bare-metal)

For always-on servers without Docker: camera.ui installs from npm and runs as a systemd service. Ubuntu 24.04 (or newer) is the tested baseline. See [System requirements](/intro/requirements).

## Prerequisites

* 64-bit Linux (x64 or arm64) with systemd
* **Node.js 24**, e.g. via [NodeSource](https://github.com/nodesource/distributions):

  ```bash
  curl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash -
  sudo apt-get install -y nodejs
  ```

FFmpeg, go2rtc and a portable Python runtime for the detection plugins are downloaded and managed by camera.ui.

## Install

```bash
sudo npm install -g camera.ui
sudo cameraui install --user cameraui
```

`cameraui install` creates the service user if it doesn't exist, registers a systemd service named `cameraui` and starts it on boot. The first start downloads the server and takes a few minutes (`sudo cameraui logs --user cameraui` shows progress). The web UI then runs on `https://<host>:3443`.

If the service user needs GPU access for hardware acceleration, add it to your distribution's `video`/`render` groups. `--group video` only applies when the install creates the user. For an existing user, run `sudo usermod -aG video cameraui` and restart the service.

## Worker mode

To run this machine as a [worker](/admin/workers) for another camera.ui server, add `--worker` to the install command:

```bash
sudo cameraui install --user cameraui --worker
```

The flag is stored with the service, so the machine comes back up as a worker after a reboot. Generate a pairing code on the main server, put the snippet into this machine's config file as described on the [workers page](/admin/workers#pair-a-worker), then run `sudo cameraui restart --user cameraui`.

## Managing the service

```bash
cameraui status                          # service state
sudo cameraui logs --user cameraui       # tail the logs
sudo cameraui restart --user cameraui    # also: start / stop
sudo cameraui update-server              # update to the latest server release
sudo cameraui update-server 1.2.3        # or pin a specific version
```

The service runs as its own user, so everything except `status` needs sudo and the same `--user` you installed with. If you installed with `-H <path>`, pass that instead.

The [Updates page](/install/updating#the-updates-page) does the same from the web interface; `update-server` is the CLI equivalent.

## Data

Everything lives in the service user's home under `~/.camera.ui` (config, database, recordings, TLS certs). That's the directory to back up. A different location can be set with `-H <path>` during install.

## Hardware acceleration

Video acceleration is [automatic](/install/hardware-acceleration), but on bare metal the host provides the drivers that the Docker images would otherwise bundle:

* **Intel GPU:** `sudo apt install intel-media-va-driver-non-free` (VA-API/QSV). For OpenVINO or OpenCL inference on the GPU, also install the OpenCL runtime: `sudo apt install ocl-icd-libopencl1 intel-opencl-icd`
* **AMD GPU:** `sudo apt install mesa-va-drivers`
* **NVIDIA:** the regular driver (e.g. `sudo ubuntu-drivers install`); the Container Toolkit is Docker-only, you don't need it here. CUDA detection with the ONNX plugin additionally needs the CUDA 13 libraries and cuDNN 9 on the system (from [NVIDIA's apt repo](https://developer.nvidia.com/cuda-downloads): `sudo apt install cuda-libraries-13-2 cudnn9-cuda-13`); the ONNX Legacy plugin wants CUDA 12 instead. The Docker images ship these, bare metal does not
* **Coral Edge TPU:** the `libedgetpu` runtime plus (for PCIe/M.2) the gasket kernel driver, see the [Coral section](/install/hardware-acceleration#coral-edge-tpu)
* **Hailo:** the kernel driver, see the [Hailo section](/install/hardware-acceleration#hailo-8-hailo-8l)

No device passthrough is needed. The detection plugins log what they found (`Available devices: …`).

## Uninstall

```bash
sudo cameraui uninstall        # removes the systemd service
sudo npm remove -g camera.ui
```

The data directory (`~/.camera.ui`) is left untouched.
