# 1.6 Shapps

A list of installation instructions, tips, gotchas and tricks for all my self hosted applications (Shapps) that I run on my home lab.

<span>Source\_1: </span>[https://techhut.tv/must-have-home-server-services-2025#hoarder](https://techhut.tv/must-have-home-server-services-2025#hoarder)

# Introduction



# 1.6.1 Docker VM Preperation

# 1.6.1.1 Docker VM Installation

The first VM we will create is the Docker VM. This VM will serve for all our docker compose files and applications that are not mission critical and are light weight applications. What is and what is not mission critical is of course for up to debate ;) Personally I have three dedicated VM's

1. One for Ente Photos
2. One for my Servarr Stack
3. My Docker VM for all my lightweight applications

In this section we will setup a Docker VM in proxmox i.e most likely your first VM. Luckily this will be extremely ease due to [Proxmox Helper scripts](https://community-scripts.org/scripts/docker-vm). Proxmox Helper scripts walks you extremely easy through the whole installation process of any LXC container and also certain VM's. In this case we will make use of it as well to create our Docker VM. Super easy, no configuration necessary from your end. Just hit the following link in your PVE Shell and you can start

```bash
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/vm/docker-vm.sh)"
```

1\. Choose Install Docker Vm

2\. Choose Advanced Setup

3\. Select the newest form of Debian as of writing that is Debian 13

4\. Enable Cloud Init: Yes

5\. Provision SSH keys for Cloud-Init VM: -&gt; Choose "manual Paste a single public key "

6\. Copy paste in your SSH key from the machine you are planning to access the Docker VM from.

7\. Set a Docker VM ID: Choose what fits for you. Most often I start with 1001

8\. Choose type: q35

9\. Choose the amount of Storage: I would recommend to start with 16G and then you can always add more over time. It is easy to add but hard to remove storage from your VM. Hence, start low and add more if necessary.

10.Disk Cache: None

11\. Choose hostname: hostname

12\. Choose CPU model: host

13\. Allocate CPU cores: Start with 4 and you can always add more if necessary

14\. RAM: start with 4096

15\. Interface: Choose the interface on which the VLAN sits that you want to use for your docker VM.

16\. Set a MAC address: Leave as is

17\. Set VLAN: The VLAN you want to host the docker VM on.

18\. Finally choose the storage pool: Recommended on your VM mirrored SSD ZFS pool if you have that configured

# 1.6.1.2 Dockge Introduction

As we will see we can either be in the terminal all the time editing docker compose files for our applications or we can attach a GUI to it.

1. [Website](https://dockge.kuma.pet/)
2. [Github Page](https://github.com/louislam/dockge)

[![image.png](https://docs.rfeyn.org/uploads/images/gallery/2026-07/scaled-1680-/4MQ8G2HPdrVVF9yd-image-png.png)](https://docs.rfeyn.org/uploads/images/gallery/2026-07/scaled-1680-/4MQ8G2HPdrVVF9yd-image-png.png)

So yeahh that is basically what Dockge is including many other features such as

- 🧑‍💼 Manage your `compose.yaml` files 
    - Create/Edit/Start/Stop/Restart/Delete
    - Update Docker Images
- ⌨️ Interactive Editor for `compose.yaml`
- 🦦 Interactive Web Terminal
- 🕷️ (1.4.0 🆕) Multiple agents support - You can manage multiple stacks from different Docker hosts in one single interface
- 🏪 Convert `docker run ...` commands into `compose.yaml`
- 📙 File based structure - Dockge won't kidnap your compose files, they are stored on your drive as usual. You can interact with them using normal `docker compose` commands
- 🚄 Reactive - Everything is just responsive. Progress (Pull/Up/Down) and terminal output are in real-time
- 🐣 Easy-to-use &amp; fancy UI - If you love Uptime Kuma's UI/UX, you will love this one too

So in this Book we will also make sure to use Dockge for all our installations. It is for sure not necessary but it is so easy and comfortable. In the next page we will do the installation.

# 1.6.1.3 Dockge Installation

Assuming you already have installed your Docker VM it is time to install Dockge on top of it to handle all your docker compose files ;)

1\. Go to the official [dockge page](https://dockge.kuma.pet/) and basically copy the docker compose file that looks like this

```yaml
services:
  dockge:
    image: louislam/dockge:1
    restart: unless-stopped
    ports:
      - 5001:5001
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./data:/app/data
      # Stacks Directory
      # ⚠️ READ IT CAREFULLY. If you did it wrong, your data could end up writing into a WRONG PATH.
      # ⚠️ 1. FULL path only. No relative path (MUST)
      # ⚠️ 2. Left Stacks Path === Right Stacks Path (MUST)
      - /opt/stacks:/opt/stacks
    environment:
      # Tell Dockge where to find the stacks
      - DOCKGE_STACKS_DIR=/opt/stacks
      # This is great for entering the Docker VM console from the WebGUI
      - DOCKGE_ENABLE_CONSOLE=true
```

2\. Then open your terminal with your access machine and SSH into it. You added the SSH key of your machine in the Cloud Init section so you should be entering without any interruptions. Simply use

<p class="callout info">ssh [username@IP-Address-Docker-VM](mailto:username@IP-Address-Docker-VM)</p>

3\. Once inside we will create a new dockge folder with

```bash
mkdir docgke
```

4\. Then we will enter the folder with

```bash
cd dockge
```

5\. Inside this folder we will create the docker compose file by copying and pasting in the docker compose content from above

```yaml
nano compose.yml
```

6\. Then save it with

CTRL X and hit Y

7\. Then we will start the dockge container with

```bash
docker compose up -d
```

8\. If everything is green and alright we should be able to access the WebGui at

<p class="callout info">IP-Address-DockerVM:5001</p>

9\. Then create an account with a username and password. Now, normally I would say you would save the credentials in your Bitwarden account but we have not yet setup that container. However, choose a non typical username and a password of 20 characters and copy paste it somewhere safe s.t you can find it. After we have created a vaultwarden container you will be able to copy paste it inside of it with all your other future credentials.

# 1.6.1.2 Dockhand

[![screenshot1.webp](https://docs.rfeyn.org/uploads/images/gallery/2026-07/scaled-1680-/NIe06o8m7WWYehgH-screenshot1-webp.webp)](https://docs.rfeyn.org/uploads/images/gallery/2026-07/scaled-1680-/NIe06o8m7WWYehgH-screenshot1-webp.webp)

<p class="callout warning">Note! At this moment you can manage remote machines via one central Dockhand instance. However, the compose files live on the Dockhand instance instead of the remote machine. This means if the central Dockhand instance would go down you would also loose the compose files on your remote machine. This ain't great and hence I prefer to have a Dockhand instance on each machine until this problem is solved. </p>

Our Stack will be using docker compose files for all its applications in this docker VM. Now, without any GUI tools this would mean that we need to edit, stop, start, and configure all applications through the terminal. Now, this is great for learning purposes and gets you to the real docker commands. However, after understanding that you can make your life easier by using a GUI that does all the docker commands in the background. Now, there are many solutions for this such as Portainer, Dockge, and others. However, the most recent kid on the block is [Dockhand](https://dockhand.pro). The amazing thing about this solutions is that it allows you to monitor your docker containers, send you alerts if something is up and send you alerts when new updates for containers are available. That last one is huge!!! It is so important to keep your containers up to date and have someone looking out for your when a new update is available is such a game changer. Instead of manually checking every week for new updates (which I always forget) it is just great that you get an email in your inbox with updates if they are available. Next to this a summary of Dockhead capabilities is.

- **Container Management**: Start, stop, restart, and monitor containers in real-time
- **Compose Stacks**: Visual editor for Docker Compose deployments
- **Git Integration**: Deploy stacks from Git repositories with webhooks and auto-sync
- **Multi-Environment**: Manage local and remote Docker hosts
- **Terminal &amp; Logs**: Interactive shell access and real-time log streaming
- **File Browser**: Browse, upload, and download files from containers
- **Authentication**: SSO via OIDC, local users, and optional RBAC (Enterprise)

#### Installation

The installation of Dockhand is fairly straightforward, the only thing you should think about is where you would like to save most of your docker compose files. This could be for instance just in /home/user/dockhand/ and you could also give it access to multiple locations inside of your VM. Personally I save everything underneath **/opt/stacks** simply because I am used to that due to Dockge that I was mainly using before Dockhand. If that's figured out you can find the docker compose on their website [ here](https://dockhand.pro).

1\. Create the Dockhand directory with

```bash
mkdir -p /opt/stacks/dockhand
```

2\. Then go inside the directory and create the following docker compose file with nano compose.yaml and copy paste the following

<details id="bkmrk-compose.yaml-service"><summary>compose.yaml</summary>

```yaml
services:
  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: dockhand
      POSTGRES_PASSWORD: changeme
      POSTGRES_DB: dockhand
    volumes:
      - ./postgres_data:/var/lib/postgresql/data

  dockhand:
    image: fnsys/dockhand:latest
    ports:
      - 3000:3000
    environment:
      DATABASE_URL: postgres://dockhand:changeme@postgres:5432/dockhand
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./dockhand_data:/app/data
      - /opt/stacks:/opt/stacks # Directory in which you plan to host docker compose files 
    depends_on:
      - postgres
    restart: unless-stopped
```

</details>3\. Sweet then what is left is

```bash
docker compose up -d
```

4\. You can then reach your Dockhand instance on [http://IP-Docker-VM:3000](http://IP-Docker-VM:3000) or the port you specified for your instance.


**Dockhand Configuration**

1\. The first thing to do when everything is up and running is creating an account for obvious security purposes

2\. Simply go to Settings &gt; Authentication &gt; Users &gt; + Add User

3\. Create a user and make sure that you check that the Authentication toggle is turned ON

##### Remote Machines

As stated in the warning above, today it is still recommended to

##### Not all your docker containers will necessarily run on the same virtual machine. However, that would also mean that you need to setup Dockhand on all these VM's. Luckily this is not necessary and you can have one glass connecting to all your docker containers on multiple VM's. 

[https://github.com/Finsys/hawser](https://github.com/Finsys/hawser)

# 1.5.2 Docusaurus

# 1.5.3 InvoiceShelf

# 1.5.2.1 Installation

**Links**

1. [Github Invoiceshelf](https://github.com/InvoiceShelf/InvoiceShelf "Github Invoiceshelf")
2. [Invoice Shelf PVE community script](https://community-scripts.org/scripts?q=invoice)

We will install Invoiceshelf as a docker compose file but it can also be installed as proxmox LXC container. At the time of writing invoiceshelf is still in heavy development and the full functionality is not added yet. However, I try to keep it as up to date as possible ;)

1\. Create a folder called invoiceshelf with

```bash
mkdir invoiceshelf
```

2\. Then the first thing we need to do is get the docker compose files by using the following commands according to the [documentation page](https://docs.invoiceshelf.com/install/docker.html)

```bash
git clone https://github.com/InvoiceShelf/docker
```

2\. This will download a collection of docker compose files and some other files. Now you can choose 3 different databases and I chose for postgresql for no particular reason

3\. In my case I like to deploy my docker compose files with [Dockge](https://dockge.kuma.pet/) and hence I will copy the contents of the **docker-compose.pgsql.yml** file and paste it into my dockge dashboard for a new container. However, you can also grab the file rename it to compose.yml and then save it in your preferred location.

4\. Next up is the docker compose file. What is important to change here are 4 things out of which three are already obvious the mysql database, user and password fields. This is clearly added as a note in the compose file

5\. Next to that you need to have a public domain name s.t customers can actually access your invoice platform and pay their bills. This domain name needs to be added 3 times at the following places

1. APP\_URL=https://invoice.example.com
2. SESSION\_DOMAIN=invoice.example.com
3. SANCTUM\_STATEFUL\_DOMAINS=invoice.example.com

6\. Finally we will add mail to it as well with the following environment variables

\- MAIL\_DRIVER=SMTP  
\- MAIL\_HOST=smtp.example.com  
\- MAIL\_PORT=587  
\- MAIL\_USERNAME=email@email.org  
\- MAIL\_PASSWORD=emailpassword  
\- MAIL\_ENCRYPTION=starttls

7\. Finally, you can decide if you keep docker volumes or mounts. I did not get it to work with mounts and hence I stayed with volumes. Since, the data quantity is pretty low it did not really matter anyways since we are not attaching an nfs share or something to it.

8\. Then it is ready to sping up the docker compose file

9\. The installation wizard is pretty simple however you need to make sure you get one thing right at the **SITE URL &amp; DATABASE** section. When it asks for the *DATABASE HOST*. In this case you need to fill in the name you gave the database container. If you have not changed anything this will be **invoiceshelf-pgsql**.

10\. Finally, also make sure you provide the right details for your email address. This will be important since from that email emails will be send to customers.

```yaml
#-------------------------------------------
# InvoiceShelf PostgresSQL docker-compose variant
# Repo : https://github.com/InvoiceShelf/docker
#-------------------------------------------

services:
  database:
    container_name: invoiceshelf-pgsql
    image: postgres:15
    environment:
      - POSTGRES_PASSWORD=sdfij2309rrjlkkfj0ejfsjdflkjsdfojwefkjHD # ⚠️ Change DB password before proceeding
      - POSTGRES_USER=invoiceshelf # ⚠️ Change DB username before proceeding
      - POSTGRES_DB=invoiceshelf # 🚨 Change DB name before proceeding
    volumes:
      - invoiceshelf_postgres:/var/lib/postgresql/data
    networks:
      - invoiceshelf
    restart: unless-stopped
  webapp:
    image: invoiceshelf/invoiceshelf:nightly
    container_name: invoiceshelf-variant-pgsql
    environment:
      - APP_NAME=InvoiceShelf
      - APP_ENV=production
      - APP_DEBUG=false
      # APP_URL should have:
      # 1. Protocol http or https if you are accessing it via reverse proxy with
      #    SSL, then it will be https, if via local IP, then http.
      # 2. IP address of the server or the domain name
      # 3. (optional) If you are using a custom port such as :8080 or another.
      # REF: https://github.com/InvoiceShelf/InvoiceShelf/issues/213#issuecomment-3026790543

      - APP_URL=https://invoice.rfeyn.org
      # SESSION_DOMAIN should have:
      # 1. IP address of the server or the domain name
      # 2. (optional) If you are using a custom port such as :8080 or another.
      # REF: https://github.com/InvoiceShelf/InvoiceShelf/issues/213#issuecomment-3026790543
      - SESSION_DOMAIN=invoice.rfeyn.org
      # SANCTUM_STATEFUL_DOMAINS should have:
      # 1. IP address of the server or the domain name
      #    1.1 (optional) If you are using a custom port such as :8080 or another.
      # 2. (optional) If you are planning to access the application from different
      #    domains, you must add a comma between each domain
      # REF: https://github.com/InvoiceShelf/InvoiceShelf/issues/213#issuecomment-3026790543
      - SANCTUM_STATEFUL_DOMAINS=invoice.rfeyn.org
      - DB_CONNECTION=pgsql
      - DB_HOST=database
      - DB_PORT=5432
      - DB_DATABASE=invoiceshelf # ⚠️ Change DB name before proceeding
      - DB_USERNAME=invoiceshelf # ⚠️ Change DB username before proceeding
      - DB_PASSWORD=sdfij2309rrjlkkfj0ejfsjdflkjsdfojwefkjHD # ⚠️ Change DB password before proceeding
      - DB_PASSWORD_FILE=
      - CACHE_STORE=file
      - SESSION_DRIVER=file
      - SESSION_LIFETIME=240
      - AUTORUN_ENABLED=true
      - AUTORUN_LARAVEL_MIGRATION=false
      - AUTORUN_LARAVEL_OPTIMIZE=false
      - PHP_OPCACHE_ENABLE=1
      - MAIL_DRIVER=SMTP
      - MAIL_HOST=smtp.porkbun.com
      - MAIL_PORT=587
      - MAIL_USERNAME=dp@p2pnode.org
      - MAIL_PASSWORD=PuV9#@pUca49C70e2V46&keg
      - MAIL_ENCRYPTION=starttls
    volumes:
      - invoiceshelf_storage:/var/www/html/storage/
      - invoiceshelf_modules:/var/www/html/Modules/
    ports:
      - 8090:8080 # 8090 is the public port.
    networks:
      - invoiceshelf
    restart: unless-stopped
    depends_on:
      - database
networks:
  invoiceshelf: null
volumes:
  invoiceshelf_postgres: null
  invoiceshelf_storage: null
  invoiceshelf_modules: null

```

<div drawio-diagram="5"><img src="https://wiki.rfeyn.org/uploads/images/drawio/2026-05/drawing-1-1779878580.png" alt="drawing-1-1779878580.png"/></div>

[Edit this Page &gt;&gt;](https://deternet.org)

# 1.5.2.3 Email Templates

#### **Nederlands**

---

#####  

##### Factuur

Beste {BILLING\_ADDRESS\_NAME},

- Er staat een factuur voor u klaar van 🐶 **{COMPANY\_NAME}** voor het uitvoeren van horeca werkzaamheden.
- Vind de factuur als PDF bestand in onderstaande link
- Mochten er vragen zijn, twijfel dan niet en bericht me meteen 😉
- Uiterste betaal datum **{INVOICE\_DUE\_DATE}** 💰
- Ontvang een betalings bevestiging 📬
- 🟥iDeal -&gt; {CUSTOM\_INVOICE\_BETAALLINK}

Met vriendelijke groet,

**DPlancer**  
Dennis Paassen  
KVK: {CUSTOM\_INVOICE\_KVK}

##### <span style="text-decoration:underline;">Betaling</span>

🚀💪Wohoooo!! Bedankt voor je betaling!!

U kunt uw betalings bevestiging vinden door op onderstaande knop te drukken

Met vriendelijke groet,

Dennis Paassen  
🐶**DPlancer**


##### **English**

---

##### Invoice

Dear {BILLING\_ADDRESS\_NAME}

- An invoice from 🐶 **{COMPANY\_NAME}** is ready for you for hospitality services
- Find the invoice as a PDF file in the link below
- If you have any questions, please don't hesitate to contact me 😉
- Invoice due date **{INVOICE\_DUE\_DATE}** 💰
- You will receive a payment confirmation 📬
- 🟥**iDeal** -&gt; {CUSTOM\_INVOICE\_BETAALLINK}

Kind regards,

**DPlancer**  
Dennis Paassen  
KVK: {CUSTOM\_INVOICE\_KVK}

##### Payment 

🚀💪Wohoooo!! Thanks for your payment

You can find your payment confirmation by clicking on the lick below

Kind regards,

Dennis Paassen  
🐶**DPlancer**

# 01. Installation

```yaml
services:
  app:
    build:
      context: .
    image: invoiceninja/invoiceninja-debian:latest
    restart: unless-stopped
    env_file:
      - ./.env
    volumes:
      - ./app_public:/var/www/html/public
      - ./app_storage:/var/www/html/storage
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy
  nginx:
    image: nginx:alpine
    restart: unless-stopped
    ports:
      - 8333:80
      - 6443:443
    volumes:
      - ./nginx:/etc/nginx/conf.d:ro
      - ./app_public:/var/www/html/public:ro
      - ./app_storage:/var/www/html/storage:ro
    depends_on:
      app:
        condition: service_healthy
  mysql:
    image: mysql:8
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: ${DB_DATABASE}
      MYSQL_USER: ${DB_USERNAME}
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
    volumes:
      - ./mysql_data:/var/lib/mysql
    healthcheck:
      test:
        - CMD
        - mysqladmin
        - ping
        - -h
        - localhost
        - -u${MYSQL_USER}
        - -p${MYSQL_PASSWORD}
  redis:
    image: redis:alpine
    restart: unless-stopped
    volumes:
      - ./redis_data:/data
    healthcheck:
      test:
        - CMD
        - redis-cli
        - ping
networks: {}

```

```yaml
# IN application vars
APP_URL=https://invoice.rfeyn.org
APP_KEY=base64:oUr5FRUWNrM42GeyksHF33ntNtlh29KW5vg2J2brnJ4=
APP_ENV=production
APP_DEBUG=true
REQUIRE_HTTPS=false
PHANTOMJS_PDF_GENERATION=true
PDF_GENERATOR=snappdf
TRUSTED_PROXIES='*'


CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis

REDIS_HOST=redis
REDIS_PASSWORD=null
REDIS_PORT=6379

FILESYSTEM_DISK=debian_docker

# DB connection
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=ninjadplancer
DB_USERNAME=ninja
DB_PASSWORD=sf9823fsjlfkjwioefjlskfh0923jfklsdjf
DB_ROOT_PASSWORD=sdpoifj293fj09030rjnsnedfo3498t
DB_CONNECTION=mysql

# Create initial user
# Default to these values if empty
IN_USER_EMAIL=dp@p2pnode.org
IN_PASSWORD=nvQi5W14blOnpv
# IN_USER_EMAIL=
# IN_PASSWORD=

# Mail options
MAIL_MAILER=log
MAIL_HOST=smtp.porkbun.com
MAIL_PORT=587
MAIL_USERNAME=dp@p2pnode.org
MAIL_PASSWORD=PuV9#@pUca49C70e2V46&keg
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS='dp@p2pnode.org'
MAIL_FROM_NAME="DPLancer Invoices"

# MySQL
MYSQL_ROOT_PASSWORD=sdpoifj293fj09030rjnsnedfo3498t
MYSQL_USER=ninja
MYSQL_PASSWORD=sf9823fsjlfkjwioefjlskfh0923jfklsdjf
MYSQL_DATABASE=ninjadplancer

# GoCardless/Nordigen API key for banking integration
NORDIGEN_SECRET_ID=
NORDIGEN_SECRET_KEY=

IS_DOCKER=true
SCOUT_DRIVER=null
#SNAPPDF_CHROMIUM_PATH=/usr/bin/google-chrome-stable
```

# 1.5.4 Nextcloud

# 1. Installation

Now, you can install nextcloud on the same docker VM that you install all other applications on as well. However, I personally have a dedicated VM for nextcloud since it is quite a heavy piece of software and if something goes wrong with nextcloud that affects the VM then it will not affect the other applications. Hence, what I first do is create again another Docker VM with the Docker VM Proxmox Helper Script. If you choose to host it on the same VM with Dockhand then you can also do this of course

<span class="monospace" id="bkmrk-ludicrous-exemption--1">ludicrous exemption constant humility trapper hardening deviancy ferocity</span>

<span class="monospace"><span class="monospace">passphrase</span></span>

<span class="monospace"><span class="monospace" id="bkmrk-ludicrous-exemption--3">ludicrous exemption constant humility trapper hardening deviancy ferocity</span></span>

<span class="monospace"><span class="monospace">10.69.1.107:11000</span></span>

<span class="monospace"><span class="monospace">The permissions should be </span></span>

# Permissions for NFS share

Right now I have 1000:1000 for and read and write permissions for everyone. Hence, that 30:00 works. But we need to figure this out for later to set the right permissions in TrueNas.

```
2026-07-08T22:31:45.606690513Z The www-data user does not appear to have access rights to the data directory.
2026-07-08T22:31:45.606704904Z It is possible that the files are on a filesystem that does not support standard Linux permissions,
2026-07-08T22:31:45.606720217Z or the permissions simply need to be adjusted. Please change the permissions as described below.
2026-07-08T22:31:45.606723395Z Current permissions are:
2026-07-08T22:31:45.609071140Z 1000:1000 770
2026-07-08T22:31:45.609597690Z (userID:groupID permissions)
2026-07-08T22:31:45.609623100Z They should be:
2026-07-08T22:31:45.609626113Z 33:0 750
2026-07-08T22:31:45.609628621Z (userID:groupID permissions)
2026-07-08T22:31:45.609630879Z Also, ensure that all parent directories on the host of your chosen data directory are publicly readable.
```

# 4. Restore From Internal Nextcloud Backup

Now, this is not necessary if you have a VM backup of your Nextcloud instance including its storage. However, if this is not the case, or you crashed your VM for whatever reason and have no backup then your can create a new nextcloud instance and import the files from a backup you must have created previously

# 1.5.5 Seafile

File Server which is dedicated for serving files! It works great for fast file synchronization due to block storage instead of file storage on Nextcloud. It is not bloated with things you don't need as it is on Nextcloud

# 1. Installation Seafile 13

We will install Seafile again in our docker vm by using Dockhand. For that we need to make sure that we have a place for all the data, which in our case will be an NFS share hosted on our TrueNas VM. Then the next step is of course to look up the docker compose file and deploy it to our needs. The docker compose file can be obtained by downloading it to your machine via [Seafile 13](https://manual.seafile.com/13.0/setup/setup_ce_by_docker/). People are working on seafile 14 as we speak. So this documentation might be outdated again on the moment you are reading this. Just make sure you check the [general website](https://manual.seafile.com/latest/) for the latest edition. So this one right now is focused on **Seafile 13**. Once 14 will be available we will update the instructions below.

Now! at this moment I don't have a running seafile 13 yet! So I still need to work on this as a project in the future. What I do realize is that you need to have root running for the storage folder. You can also do this without root but also I don't know yet how to do that. For now make sure your TrueNas NFS share has root as the owner.

1. **Make sure you have compose.yml**
2. **Also you need to run seadoc if you want to have the wiki function. Make sure you copy paste the values from the seafile mysql database**
3. **Create an .env file that serves compose.yml and the seadoc file**

<details id="bkmrk-compose.yml-services"><summary>compose.yml</summary>

```yaml
services:
  db:
    image: ${SEAFILE_DB_IMAGE:-mariadb:10.11}
    container_name: seafile-mysql
    restart: unless-stopped
    environment:
      - MYSQL_ROOT_PASSWORD=${INIT_SEAFILE_MYSQL_ROOT_PASSWORD:-}
      - MYSQL_LOG_CONSOLE=true
      - MARIADB_AUTO_UPGRADE=1
    volumes:
      - "${SEAFILE_MYSQL_VOLUME:-/opt/seafile-mysql/db}:/var/lib/mysql"
    networks:
      - seafile-net
    healthcheck:
      test:
        [
          "CMD",
          "/usr/local/bin/healthcheck.sh",
          "--connect",
          "--mariadbupgrade",
          "--innodb_initialized",
        ]
      interval: 20s
      start_period: 30s
      timeout: 5s
      retries: 10

  redis:
    image: ${SEAFILE_REDIS_IMAGE:-redis}
    container_name: seafile-redis
    restart: unless-stopped
    command:
      - /bin/sh
      - -c
      - redis-server --requirepass "$$REDIS_PASSWORD"
    environment:
      - REDIS_PASSWORD=${REDIS_PASSWORD:-}
    networks:
      - seafile-net

  seafile:
    image: ${SEAFILE_IMAGE:-seafileltd/seafile-mc:13.0-latest}
    container_name: seafile
    restart: unless-stopped
    # ports:
    #   - "80:80"
    volumes:
      - ${SEAFILE_VOLUME:-/opt/seafile-data}:/shared
    environment:
      - SEAFILE_MYSQL_DB_HOST=${SEAFILE_MYSQL_DB_HOST:-db}
      - SEAFILE_MYSQL_DB_PORT=${SEAFILE_MYSQL_DB_PORT:-3306}
      - SEAFILE_MYSQL_DB_USER=${SEAFILE_MYSQL_DB_USER:-seafile}
      - SEAFILE_MYSQL_DB_PASSWORD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
      - INIT_SEAFILE_MYSQL_ROOT_PASSWORD=${INIT_SEAFILE_MYSQL_ROOT_PASSWORD:-}
      - SEAFILE_MYSQL_DB_CCNET_DB_NAME=${SEAFILE_MYSQL_DB_CCNET_DB_NAME:-ccnet_db}
      - SEAFILE_MYSQL_DB_SEAFILE_DB_NAME=${SEAFILE_MYSQL_DB_SEAFILE_DB_NAME:-seafile_db}
      - SEAFILE_MYSQL_DB_SEAHUB_DB_NAME=${SEAFILE_MYSQL_DB_SEAHUB_DB_NAME:-seahub_db}
      - TIME_ZONE=${TIME_ZONE:-Etc/UTC}
      - INIT_SEAFILE_ADMIN_EMAIL=${INIT_SEAFILE_ADMIN_EMAIL:-me@example.com}
      - INIT_SEAFILE_ADMIN_PASSWORD=${INIT_SEAFILE_ADMIN_PASSWORD:-asecret}
      - SEAFILE_SERVER_HOSTNAME=${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
      - SEAFILE_SERVER_PROTOCOL=${SEAFILE_SERVER_PROTOCOL:-http}
      - SITE_ROOT=${SITE_ROOT:-/}
      - NON_ROOT=${NON_ROOT:-false}
      - JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
      - SEAFILE_LOG_TO_STDOUT=${SEAFILE_LOG_TO_STDOUT:-false}
      - ENABLE_GO_FILESERVER=${ENABLE_GO_FILESERVER:-true}
      - ENABLE_SEADOC=${ENABLE_SEADOC:-true}
      - SEADOC_SERVER_URL=${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}/sdoc-server
      - CACHE_PROVIDER=${CACHE_PROVIDER:-redis}
      - REDIS_HOST=${REDIS_HOST:-redis}
      - REDIS_PORT=${REDIS_PORT:-6379}
      - REDIS_PASSWORD=${REDIS_PASSWORD:-}
      - MEMCACHED_HOST=${MEMCACHED_HOST:-memcached}
      - MEMCACHED_PORT=${MEMCACHED_PORT:-11211}
      - ENABLE_NOTIFICATION_SERVER=${ENABLE_NOTIFICATION_SERVER:-false}
      - INNER_NOTIFICATION_SERVER_URL=${INNER_NOTIFICATION_SERVER_URL:-http://notification-server:8083}
      - NOTIFICATION_SERVER_URL=${NOTIFICATION_SERVER_URL:-${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}/notification}
      - ENABLE_SEAFILE_AI=${ENABLE_SEAFILE_AI:-false}
      - ENABLE_FACE_RECOGNITION=${ENABLE_FACE_RECOGNITION:-false}
      - SEAFILE_AI_SERVER_URL=${SEAFILE_AI_SERVER_URL:-http://seafile-ai:8888}
      - SEAFILE_AI_SECRET_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
      - MD_FILE_COUNT_LIMIT=${MD_FILE_COUNT_LIMIT:-100000}
    labels:
      caddy: ${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
      caddy.reverse_proxy: "{{upstreams 80}}"
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:80 || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    networks:
      - seafile-net

networks:
  seafile-net:
    name: seafile-net

```

</details><details id="bkmrk-.env-%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23"><summary>.env</summary>

```
#################################
# Docker compose configurations #
#################################
COMPOSE_FILE='seafile-server.yml,caddy.yml,seadoc.yml'
COMPOSE_PATH_SEPARATOR=','

## Images
SEAFILE_IMAGE=seafileltd/seafile-mc:13.0-latest
SEAFILE_DB_IMAGE=mariadb:10.11
SEAFILE_REDIS_IMAGE=redis
SEAFILE_CADDY_IMAGE=lucaslorentz/caddy-docker-proxy:2.12-alpine
SEADOC_IMAGE=seafileltd/sdoc-server:2.0-latest
NOTIFICATION_SERVER_IMAGE=seafileltd/notification-server:13.0-latest
MD_IMAGE=seafileltd/seafile-md-server:13.0-latest

## Persistent Storage
BASIC_STORAGE_PATH=/opt
SEAFILE_VOLUME=$BASIC_STORAGE_PATH/seafile-data
SEAFILE_MYSQL_VOLUME=$BASIC_STORAGE_PATH/seafile-mysql/db
SEAFILE_CADDY_VOLUME=$BASIC_STORAGE_PATH/seafile-caddy
SEADOC_VOLUME=$BASIC_STORAGE_PATH/seadoc-data

#################################
#      Startup parameters       #
#################################
SEAFILE_SERVER_HOSTNAME=seafile.example.com
SEAFILE_SERVER_PROTOCOL=http
TIME_ZONE=Etc/UTC
JWT_PRIVATE_KEY=

#####################################
# Third-party service configuration #
#####################################

## Database
SEAFILE_MYSQL_DB_HOST=db
SEAFILE_MYSQL_DB_USER=seafile
SEAFILE_MYSQL_DB_PASSWORD=PASSWORD
SEAFILE_MYSQL_DB_CCNET_DB_NAME=ccnet_db
SEAFILE_MYSQL_DB_SEAFILE_DB_NAME=seafile_db
SEAFILE_MYSQL_DB_SEAHUB_DB_NAME=seahub_db

## Cache
CACHE_PROVIDER=redis # or memcached


### Redis
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=

### Memcached
MEMCACHED_HOST=memcached
MEMCACHED_PORT=11211

######################################
#        Initial variables           #
# (Only valid in first-time startup) #
######################################

## Database root password, Used to create Seafile users
INIT_SEAFILE_MYSQL_ROOT_PASSWORD=ROOT_PASSWORD

## Seafile admin user
INIT_SEAFILE_ADMIN_EMAIL=me@example.com
INIT_SEAFILE_ADMIN_PASSWORD=asecret

############################################
# Additional configurations for extensions #
############################## Seafile AI
ENABLE_SEAFILE_AI=false
ENABLE_FACE_RECOGNITION=false
SEAFILE_AI_LLM_TYPE=openai
SEAFILE_AI_LLM_URL=
SEAFILE_AI_LLM_KEY= # your llm key
SEAFILE_AI_LLM_MODEL=gpt-4o-mini

## Metadata server
MD_FILE_COUNT_LIMIT=100000
################

## SeaDoc service
ENABLE_SEADOC=true

## Notification
ENABLE_NOTIFICATION_SERVER=false
NOTIFICATION_SERVER_URL=

```

</details><details id="bkmrk-compose.yml-%C2%A0-servic"><summary>compose.yml</summary>

```yaml
services:
  db:
    image: mariadb:10.11
    container_name: seafile-db
    environment:
      - MYSQL_ROOT_PASSWORD=${SEAFILE_PASSWORD}
      - MYSQL_LOG_CONSOLE=true
      - MARIADB_AUTO_UPGRADE=1
    volumes:
      - ./mysql:/var/lib/mysql
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 20s
      start_period: 30s
      timeout: 5s
      retries: 10

  redis:
    image: redis:7
    container_name: seafile-redis
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 20s
      timeout: 5s
      retries: 5

  seafile:
    image: seafileltd/seafile-mc:13.0-latest
    container_name: seafile
    ports:
      - "1026:80"
    volumes:
      - /mnt/seafile:/shared
    environment:
      # Core
      - SEAFILE_SERVER_HOSTNAME=${SEAFILE_SERVER_HOSTNAME}
      - SEAFILE_SERVER_PROTOCOL=${SEAFILE_SERVER_PROTOCOL}
      - TIME_ZONE=${TIME_ZONE}
      - JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY}

      # Database
      - DB_HOST=db
      - DB_ROOT_PASSWD=${SEAFILE_PASSWORD}
      - SEAFILE_MYSQL_DB_HOST=db
      - SEAFILE_MYSQL_DB_USER=seafile
      - SEAFILE_MYSQL_DB_PASSWORD=${SEAFILE_PASSWORD}
      - SEAFILE_MYSQL_DB_CCNET_DB_NAME=ccnet_db
      - SEAFILE_MYSQL_DB_SEAFILE_DB_NAME=seafile_db
      - SEAFILE_MYSQL_DB_SEAHUB_DB_NAME=seahub_db

      # Cache
      - CACHE_PROVIDER=redis
      - REDIS_HOST=redis
      - REDIS_PORT=6379

      # First-run admin bootstrap (ignored on subsequent starts)
      - INIT_SEAFILE_ADMIN_EMAIL=${SEAFILE_ADMIN_EMAIL}
      - INIT_SEAFILE_ADMIN_PASSWORD=${SEAFILE_PASSWORD}
      - INIT_SEAFILE_MYSQL_ROOT_PASSWORD=${SEAFILE_PASSWORD}
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    restart: unless-stopped
```

</details><details id="bkmrk-.env-%23-%3D%3D%3D%3D-hostname"><summary>.env</summary>

```yaml
# ==== Hostname ====
# Bake-in on first run - the domain or IP:port you will actually use to reach Seafile.
# Do NOT change after first boot without also editing conf/seahub_settings.py.
SEAFILE_SERVER_HOSTNAME=10.69.1.106
SEAFILE_SERVER_PROTOCOL=http
TIME_ZONE=Europe/Amsterdam

# ==== Secrets ====
# Paste the output of: openssl rand -base64 40
JWT_PRIVATE_KEY=m41h+mivVsScLtvik+ebyiPvyjlhiZ1HgeIAjkp5J92aQqnda7uLkQ==

# ONE password used for everything: MariaDB root, Seafile's DB user, and the Seafile web admin.
# Pick a strong unique value.
SEAFILE_PASSWORD=NKetpcGDPqCXGlBYATTTZ26E438Ns1FOPoqlUX0QeOGmgsEYSBToAg==

# Admin email for the first-boot web UI login (only used on first startup).
SEAFILE_ADMIN_EMAIL=dp@p2pnode.org
```

</details>

# 1.5.6 Penpot

# 1.5.7 Vaultwarden

# 1.5.8 Jellyfin

# 1. Installation

For Jellyfin we wil install it in the following way

# 1.5.9 Emby

# 1.5.10 Karakeep

# 1.5.11 Linkwarden

# 1.5.12 Penpot

<span>Penpot is the open-source design platform for teams that need scalable collaboration.</span>

# 01. Installation

The installation of Penpot is quite straightforward.

According to its own official [documentation](https://help.penpot.app/technical-guide/getting-started/docker/) the first step we need to do is obtaining all the resources necessary to run Penpot as a docker container with the following command

```bash
wget https://raw.githubusercontent.com/penpot/penpot/main/docker/images/docker-compose.yaml
```

If you follow along with the Dockge installations it is recommended to run this inside the /opt/stacks directory such that it sits directly in the directory that Dockge can access it.

# 1.5.13 Nexterm

# 1. Installation

Source: [https://nexterm.dev/install](https://nexterm.dev/install)

# 1.5.14 Invoice Ninja

Invoice Ninja is a free, open-source invoicing, expenses, and time-tracking application for freelancers and small businesses, offering features like custom-branded invoices, recurring billing, online payments via 40+ gateways, project and task management, and expense tracking

<span>Invoice Ninja is by far the most comfortable invoice system that I have used so far for my small freelance business in the hospitality industry. It has more features that I will ever need but it makes invoicing employers just so streamlined and easy. Instead of manually making all your invoices, sending emails, keeping track of payments, due dates, manual payments and more. Invoice Ninja makes this all a smooth experience for both you and the person that needs to pay you. </span>

# 01. Docker Installation

Alright, so if you have a small business or you are simply a freelancer in any field then Invoice Ninja might be for you. It is quite an easy install but you need to know a couple of gotcha's to get things rolling. I show you here my method that works for me, and you can just copy paste that. However, there are of course other workflows possible as well.

According to its official documentation

<details id="bkmrk-docker-compose-file-"><summary>Docker Compose File</summary>

```yaml
services:
  app:
    build:
      context: .
    image: invoiceninja/invoiceninja-debian:${TAG:-latest}
    restart: unless-stopped
    env_file:
      - ./.env
    volumes:
      # - ./php/php.ini:/usr/local/etc/php/conf.d/invoiceninja.ini:ro
      # - ./php/php-fpm.conf:/usr/local/etc/php-fpm.d/invoiceninja.conf:ro
      # - ./supervisor/supervisord.conf:/etc/supervisor/conf.d/supervisord.conf:ro
      - app_public:/var/www/html/public
      - app_storage:/var/www/html/storage
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy
  nginx:
    image: nginx:alpine
    restart: unless-stopped
    ports:
      - 8333:80
    volumes:
      - ./nginx:/etc/nginx/conf.d:ro
      - app_public:/var/www/html/public:ro
      - app_storage:/var/www/html/storage:ro
    depends_on:
      app:
        condition: service_healthy
  mysql:
    image: mysql:8
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: ${DB_DATABASE}
      MYSQL_USER: ${DB_USERNAME}
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
    volumes:
      - mysql_data:/var/lib/mysql
    healthcheck:
      test:
        - CMD
        - mysqladmin
        - ping
        - -h
        - localhost
        - -u${MYSQL_USER}
        - -p${MYSQL_PASSWORD}
  redis:
    image: redis:alpine
    restart: unless-stopped
    volumes:
      - redis_data:/data
    healthcheck:
      test:
        - CMD
        - redis-cli
        - ping
volumes:
  app_public:
    driver: local
  app_storage:
    driver: local
  mysql_data:
    driver: local
  redis_data:
    driver: local
networks: {}

```

</details><details id="bkmrk-.env-%23-in-applicatio"><summary>.env</summary>

```yaml
# IN application vars
TAG=latest
APP_URL=https://invoice.rfeyn.org
APP_KEY=base64:gDCwop+h+/KcHsrCzc7tt4lbqcqH8hzMnm3x3+8oGnM=
API_SECRET=Kikkers49$91
APP_ENV=production
APP_DEBUG=true
REQUIRE_HTTPS=false
PHANTOMJS_PDF_GENERATION=false #Turn this function off to generate pdf with snappdf
PDF_GENERATOR=snappdf
TRUSTED_PROXIES='*'


CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis

REDIS_HOST=redis
REDIS_PASSWORD=null
REDIS_PORT=6379

FILESYSTEM_DISK=debian_docker

# DB connection
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=ninjadplancer
DB_USERNAME=ninja
DB_PASSWORD=sf9823fsjlfkjwioefjlskfh0923jfklsdjf
DB_ROOT_PASSWORD=sdpoifj293fj09030rjnsnedfo3498t
DB_CONNECTION=mysql

# Create initial user
# Default to these values if empty
IN_USER_EMAIL=dp@p2pnode.org
IN_PASSWORD=nvQi5W14blOnpv
# IN_USER_EMAIL=
# IN_PASSWORD=

# Mail options
MAIL_MAILER=log
MAIL_HOST=smtp.porkbun.com
MAIL_PORT=587
MAIL_USERNAME=dp@p2pnode.org
MAIL_PASSWORD=PuV9#@pUca49C70e2V46&keg
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS='dp@p2pnode.org'
MAIL_FROM_NAME="DPLancer Invoices"

# MySQL
MYSQL_ROOT_PASSWORD=sdpoifj293fj09030rjnsnedfo3498t
MYSQL_USER=ninja
MYSQL_PASSWORD=sf9823fsjlfkjwioefjlskfh0923jfklsdjf
MYSQL_DATABASE=ninjadplancer

# GoCardless/Nordigen API key for banking integration
NORDIGEN_SECRET_ID=
NORDIGEN_SECRET_KEY=

IS_DOCKER=true
SCOUT_DRIVER=null
#SNAPPDF_CHROMIUM_PATH=/usr/bin/google-chrome-stable

```

</details>2\.

# 02. Payment Integrations (Mollie)

After you have successfully installed Invoice Ninja and created an account it is time to connect a payment integration with it. You don't need to have a payment integration to use Invoice Ninja, however if you went through the hassle of installing it you better do it ;) Yes the integrations are not fully open source but it's the best we have so far

1\. Go to Settings --&gt; Payment Settings --&gt; Add Payment Gateway

2\. Then choose a payment gateway that suits your needs. This could be for instance Stripe for USA and Mollie for European customers. I am from the Netherlands where most people use iDeal/Wero for their payments. Hence, I went with Mollie for my personal invoice ninja instance for my hospitality business. Hence, the following is a Mollie integration but it would work the same for any other payment gateway.

3\. In the case of Mollie create an account and make sure you provide them with a business website or a proper description of your business. This is necessary for them to accept iDeal payments for instance.

4\. If the iDeal payments are not accepted automatically after one day then I would recommend to contact support. This is what I did and they accepted it straight away.

5\. If that is all set you need to obtain an API key and a Profile ID.

6\. Inside of Mollie click on "Developers" that sits in the left bottom corner of your dashboard.

7\. Then choose API Access Tokens -&gt; + Create new Token

8\.

# 03. Localization

This is a short page, but it is of importance! If you operate in country X you would like that the emails and client portals your clients interact with is in language X. This is where localization comes in.

1. Go to Settings -&gt; Localization
2. Then select the right language, timezone and date format for the country you are operating in.

# 1.5.15 Frigate NVR

# 01. Frigate Installation

<details id="bkmrk-configuration-file-m"><summary>Configuration File</summary>

```yaml
mqtt:
  enabled: true
  host: 10.131.2.131
  user: peaske  
  password: 7&QpP1qBKikkers49$91

semantic_search:
  enabled: true
  reindex: false

record:
  enabled: true
  continuous:
    days: 14

snapshots:
  enabled: true
  retain:
    default: 14
  required_zones: [cam_1_person, cam_2_person, cam_3_person, cam_4_person, 
        cam_5_person, cam_6_person, cam_7_person, cam_8_person, cam_9_person]
  # Optional: Camera override for retention settings (default: global values)

objects:
  track:
    - person

cameras:     # No cameras defined, UI wizard should be used
  cam_1:
    enabled: true
    ffmpeg:
      inputs:
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.101:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
          roles:
            - record
            - audio
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.101:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
          roles:
            - detect
    objects:
      track:
        - person
        - car
    detect:
      enabled: true
      width: 1280
      height: 720
      fps: 5
    review:
      alerts:
        labels:
          - person
          - car
        required_zones:
          - cam_1_person
    #      - cam_1_car
      detections:
        labels:
          - person
        required_zones:
          - cam_1_person
    #      - cam_1_car
    live:
      streams:
        Stream 1: cam_1_1
        Stream 2: cam_1_2
    notifications:
      enabled: true
    zones:
      cam_1_person:
        coordinates: 0.679,0.187,0.407,0.989,0.668,0.997,0.72,0.593,0.737,0.195
        inertia: 3
        loitering_time: 0
        objects: person
      #cam_1_car:
      #  coordinates: 0.539,0.127,0.285,0.374,0.073,0.772,0.186,1,0.651,0.149
      #  loitering_time: 0
      #  inertia: 3
      #  objects: car
  cam_2:
    enabled: true
    ffmpeg:
      inputs:
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.102:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
          roles:
            - record
            - audio
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.102:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
          roles:
            - detect
    detect:
      enabled: true
      width: 1280
      height: 720
      fps: 5
    review:
      alerts:
        labels:
          - person
        required_zones:
          - cam_2_person
      detections:
        labels:
          - person
        required_zones:
          - cam_2_person
    live:
      streams:
        Stream 1: cam_2_1
        Stream 2: cam_2_2
    notifications:
      enabled: true
    zones:
      cam_2_person:
        coordinates: 0.483,0.265,0.35,0.998,0.754,0.992,0.582,0.009
        loitering_time: 0
        objects: person
    objects:
      filters:
        person:
          mask: 0.004,0.011,0.003,0.991,0.335,0.992,0.478,0.241,0.57,0.008
  cam_3:
    enabled: true
    ffmpeg:
      inputs:
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.103:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
          roles:
            - record
            - audio
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.103:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
          roles:
            - detect
    detect:
      enabled: true
      width: 1280
      height: 720
      fps: 5
    review:
      alerts:
        labels:
          - person
        required_zones:
          - cam_3_person
      detections:
        labels:
          - person
        required_zones:
          - cam_3_person
    live:
      streams:
        Stream 1: cam_3_1
        Stream 2: cam_3_2
    zones:
      cam_3_person:
        coordinates: 0.497,0.106,0.59,0.991,0.462,0.992,0.45,0.13
        loitering_time: 0
        objects: person
    objects:
      filters:
        person:
          mask: 
            0.506,0.113,0.601,0.982,0.995,0.989,0.992,0.018,0.545,0,0.61,0.087
  cam_4:
    enabled: true
    ffmpeg:
      inputs:
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.104:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
          roles:
            - record
            - audio
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.104:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
          roles:
            - detect
    detect:
      enabled: true
      width: 1280
      height: 720
      fps: 5
    review:
      alerts:
        labels:
          - person
        required_zones:
          - cam_4_person
      detections:
        labels:
          - person
        required_zones:
          - cam_4_person
    live:
      streams:
        Stream 1: cam_4_1
        Stream 2: cam_4_2
    notifications:
      enabled: true
    zones:
      cam_4_person:
        coordinates: 0.593,0.465,0.712,0.994,0.366,0.997,0.374,0.466
        loitering_time: 0
        objects: person
    objects:
      mask: 
        0.311,0.005,0.359,0.431,0.664,0.437,0.817,0.995,0.995,0.998,0.994,0.009
  cam_5:
    enabled: true
    ffmpeg:
      inputs:
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.105:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
          roles:
            - record
            - audio
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.105:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
          roles:
            - detect
    detect:
      enabled: true
      width: 1280
      height: 720
      fps: 5
    review:
      alerts:
        labels:
          - person
        required_zones:
          - cam_5_person
      detections:
        labels:
          - person
        required_zones:
          - cam_5_person
    live:
      streams:
        Stream 1: cam_5_1
        Stream 2: cam_5_2
    notifications:
      enabled: true
    zones:
      cam_5_person:
        coordinates: 0.534,0.116,0.517,0.991,0.332,0.998,0.491,0.113
        loitering_time: 0
        objects: person
    objects:
      mask: 0.004,0.005,0.006,0.997,0.315,0.994,0.491,0.023
  cam_6:
    enabled: true
    ffmpeg:
      inputs:
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.106:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
          roles:
            - record
            - audio
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.106:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
          roles:
            - detect
    detect:
      enabled: true
      width: 1280
      height: 720
      fps: 5
    review:
      alerts:
        labels:
          - person
        required_zones:
          - cam_6_person
      detections:
        labels:
          - person
        required_zones:
          - cam_6_person
    live:
      streams:
        Stream 1: cam_6_1
        Stream 2: cam_6_2
    notifications:
      enabled: true
    zones:
      cam_6_person:
        coordinates: 0.225,0.198,0.279,0.593,0.346,0.998,0.489,1,0.253,0.166
        loitering_time: 0
        objects: person
    objects:
      mask:
        - 0.267,0.008,0.264,0.157,0.505,0.997,0.99,0.986,0.991,0.011
        - 0.003,0.008,0.007,0.994,0.31,0.991,0.194,0.017
  cam_7:
    enabled: true
    ffmpeg:
      inputs:
        - path: rtsp://127.0.0.1:8554/cam_7_1
          input_args: preset-rtsp-restream
          roles:
            - record
            - audio
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.107:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
          roles:
            - detect
    detect:
      enabled: true
      width: 1280
      height: 720
      fps: 5
    review:
      alerts:
        labels:
          - person
        required_zones:
          - cam_7_person
      detections:
        labels:
          - person
        required_zones:
          - cam_7_person
    live:
      streams:
        Stream 1: cam_7_1
        Stream 2: cam_7_2
    notifications:
      enabled: true
    zones:
      cam_7_person:
        coordinates: 0.519,0.071,0.603,0.991,0.806,0.991,0.595,0.027
        loitering_time: 0
        objects: person
    objects:
      mask:
        - 0.005,0.015,0.009,0.986,0.436,0.991,0.457,0.015
        - 0.614,0.014,0.835,0.992,0.996,0.988,0.997,0.009
  cam_8:
    enabled: true
    ffmpeg:
      inputs:
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.108:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
          roles:
            - record
            - audio
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.108:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
          roles:
            - detect
    detect:
      enabled: true
      width: 1280
      height: 720
      fps: 5
    review:
      alerts:
        labels:
          - person
        required_zones:
          - cam_8_person
      detections:
        labels:
          - person
        required_zones:
          - cam_8_person
    live:
      streams:
        Stream 1: cam_8_1
        Stream 2: cam_8_2
    notifications:
      enabled: true
    zones:
      cam_8_person:
        coordinates: 
          0.287,0.585,0.092,0.753,0.126,0.887,0.19,1,0.356,0.931,0.477,0.694
        loitering_time: 0
        objects: person
  cam_9:
    enabled: true
    ffmpeg:
      inputs:
        - path: rtsp://127.0.0.1:8554/cam_9_1
          input_args: preset-rtsp-restream
          roles:
            - record
            - audio
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.109:554/cam/realmonitor?channel=1&subtype=1
          roles:
            - detect
    detect:
      enabled: true
      width: 1280
      height: 720
      fps: 5
    review:
      alerts:
        labels:
          - person
        required_zones:
          - cam_9_person
      detections:
        labels:
          - person
        required_zones:
          - cam_9_person
    live:
      streams:
        Stream 1: cam_9_1
        Stream 2: cam_9_2
    notifications:
      enabled: true
    zones:
      cam_9_person:
        coordinates: 0.362,0.184,0.703,0.52,0.554,0.971,0.365,0.973,0.128,0.588
        loitering_time: 0
        objects: person
version: 0.17-0
go2rtc:
  streams:
    cam_1_1:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.101:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
    cam_1_2:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.101:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
    cam_2_1:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.102:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
    cam_2_2:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.102:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
    cam_3_1:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.103:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
    cam_3_2:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.103:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
    cam_4_1:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.104:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
    cam_4_2:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.104:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
    cam_5_1:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.105:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
    cam_5_2:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.105:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
    cam_6_1:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.106:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
    cam_6_2:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.106:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
    cam_7_1:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.107:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
    cam_7_2:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.107:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
    cam_8_1:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.108:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
    cam_8_2:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.108:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
    cam_9_1:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.109:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
    cam_9_2:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.109:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif

notifications:
  enabled: true
  email: dp@p2pnode.org


```

</details>Snapshot

Alerts

Detections

Recording

```yaml
objects:
  track:
    #- person
    #- car
  filters:
    person:
      min_score: .60
      threshold: .65
    car:
      min_score: .60
      threshold: .65
```

<details id="bkmrk-compose-file-service"><summary>Compose file</summary>

```yaml
services:
  frigate:
    mem_limit: 5g
    container_name: frigate
    privileged: true # this may not be necessary for all setups
    restart: unless-stopped
    stop_grace_period: 30s # allow enough time to shut down the various services
    image: ghcr.io/blakeblackshear/frigate:stable
    shm_size: "1000mb" # update for your cameras based on calculation above
    devices:
   #   - /dev/bus/usb:/dev/bus/usb # Passes the USB Coral, needs to be modified for other versions
   #   - /dev/apex_0:/dev/apex_0 # Passes a PCIe Coral, follow driver instructions here https://coral.ai/docs/m2/get-started/#2a-on-linux
   #   - /dev/video11:/dev/video11 # For Raspberry Pi 4B
   #   - /dev/dri/card0:/dev/dri/card0 # For intel hwaccel, needs to be updated for your hardware
      - /dev/dri/renderD128:/dev/dri/renderD128 # For intel hwaccel, needs to be updated for your hardware   
    volumes:
      - ./etc/localtime:/etc/localtime:ro
      - ./config:/config
      - ./media:/media/frigate
      - type: tmpfs # Optional: 1GB of memory, reduces SSD/SD Card wear
        target: /tmp/cache
        tmpfs:
          size: 1000000000
    ports:
      - 8971:8971
      - 8080:8080
      - 5000:5000 # Internal unauthenticated access. Expose carefully.
      - 8554:8554 # RTSP feeds
      - 8555:8555/tcp # WebRTC over tcp
      - 8555:8555/udp # WebRTC over udp
    environment:
      FRIGATE_RTSP_PASSWORD: "Stel137&QpP1qB"
  mqtt:
    mem_limit: 1g
    image: eclipse-mosquitto:latest
    container_name: mqtt
    restart: unless-stopped
    volumes:
      - ./mosquitto/config:/mosquitto/config
      - ./mosquitto/data:/mosquitto/data
      - ./mosquitto/log:/mosquitto/log
    ports:
      - 1883:1883

```

</details>```yaml
# With 1280x720 detect resolution

mqtt:
  host: mqtt # The hostname of mqtt in the docker compose file
  topic_prefix: frigate
  enabled: true

# _______________________________________Detection______________________________________

#ffmpeg: #If you use an AMD CPU for detection then leave this whole section uncommented
#  hwaccel_args: preset-vaapi
#  output_args: 
#    record: preset-record-generic-audi-aac

#detectors:
#  ov_0:
#    type: openvino
#    device: CPU
#  ov_1:
#    type: openvino
#    device: CPU
#  ov_2:
#    type: openvino
#    device: CPU


#logger:
#  default: info
#  logs:
#    frigate.video: debug  # Enable FFmpeg debug logs
#ffmpeg:
#  input_args:
#    - hwaccel
#    - vaapi        
#    - rtsp_transport
#    - tcp
#
# ----------------------------------------Timezone ------------------------------------
# This makes sure that Frigate always uses the local time and does not switch to another 
# Timezone when it is viewed remotely.

ui:
  timezone: Europe/Berlin

# ----------------------------------------Tracked Objects ------------------------------------

objects:
  track:
    - person
    - car
  filters:
    person:
      min_score: .60
      threshold: .65
    car:
      min_score: .60
      threshold: .65

detect:
  enabled: true
go2rtc:
  streams:
    cam1:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.101/cam/realmonitor?channel=1&subtype=0
    cam1_sub:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.101/cam/realmonitor?channel=1&subtype=1
    cam2:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.102/cam/realmonitor?channel=1&subtype=0
    cam2_sub:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.102/cam/realmonitor?channel=1&subtype=1
    cam3:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.103/cam/realmonitor?channel=1&subtype=0
    cam3_sub:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.103/cam/realmonitor?channel=1&subtype=1
    cam4:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.104/cam/realmonitor?channel=1&subtype=0
    cam4_sub:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.104/cam/realmonitor?channel=1&subtype=1
    cam5:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.105/cam/realmonitor?channel=1&subtype=0
    cam5_sub:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.105/cam/realmonitor?channel=1&subtype=1
    cam6:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.106/cam/realmonitor?channel=1&subtype=0
    cam6_sub:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.106/cam/realmonitor?channel=1&subtype=1
    cam7:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.107/cam/realmonitor?channel=1&subtype=0
    cam7_sub:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.107/cam/realmonitor?channel=1&subtype=1
    cam8:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.108/cam/realmonitor?channel=1&subtype=0
    cam8_sub:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.108/cam/realmonitor?channel=1&subtype=1
    cam9:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.109/cam/realmonitor?channel=1&subtype=0
    cam9_sub:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.109/cam/realmonitor?channel=1&subtype=1


cameras:
# ----------------------------------------CAM 1 ------------------------------------
  cam1:
    review:
      alerts:
        required_zones: cam1_parking_lot
      detections:
        required_zones: cam1_parking_lot
    lpr:
      enabled: false
    ffmpeg:
      inputs:
        - path: rtsp://127.0.0.1:8554/cam1_sub
          input_args: preset-rtsp-restream
          roles:
            - detect
        - path: rtsp://127.0.0.1:8554/cam1
          input_args: preset-rtsp-restream
          roles:
            - record
      output_args:
        record: preset-record-generic-audio-aac
    detect:
      width: 1280
      height: 720
      fps: 5
    objects:
      track:
        - person
        - car
      filters:
        person:
          mask: 0,1,0.117,1,0.236,0.86,0.649,0.13,0.719,0,0.625,0,0,0
    snapshots:
      required_zones:
        - cam1_parking_lot
      enabled: true
      timestamp: true
      bounding_box: true
      crop: true
      height: 500
      retain:
        default: 14
    record:
      enabled: true
      alerts:
        retain:
          days: 14
        pre_capture: 15
        post_capture: 15
      detections:
        retain:
          days: 14
        pre_capture: 15
        post_capture: 15
      continuous:
        retain:
          days: 14
      motion:
        days: 0
    notifications:
      enabled: true

    zones:
      cam1_parking_lot:
        coordinates: 
          0.235,0.881,0.129,1,0.487,1,0.678,0.997,0.741,0.47,0.747,0.207,0.752,0,0.733,0,0.715,0.026,0.495,0.423,0.485,0.437
        inertia: 3
        loitering_time: 0
    motion:
      mask: 
        0.742,0,0.745,0.204,0.741,0.46,0.718,0.719,0.678,0.998,0.996,0.998,0.994,0.003

# ----------------------------------------CAM 2 ------------------------------------

  cam2:
    review:
      alerts:
        required_zones: cam2_person
      detections:
        required_zones: cam2_person
    lpr:
      enabled: false
    ffmpeg:
      inputs:
        - path: rtsp://127.0.0.1:8554/cam2_sub
          input_args: preset-rtsp-restream
          roles:
            - detect
        - path: rtsp://127.0.0.1:8554/cam2
          input_args: preset-rtsp-restream
          roles:
            - record
      output_args:
        record: preset-record-generic-audio-aac
    detect:
      width: 1280
      height: 720
      fps: 5
    objects:
      track:
        - person
      filters:
        person:
          min_area: 2000
          max_area: 90000
      mask: 0,0,0,1,0.373,1,0.56,0
    snapshots:
      required_zones:
        - cam2_person
      enabled: true
      timestamp: true
      bounding_box: true
      crop: true
      height: 500
      retain:
        default: 14
    record:
      enabled: true
      alerts:
        retain:
          days: 14
        pre_capture: 15
        post_capture: 15
      detections:
        retain:
          days: 14
        pre_capture: 15
        post_capture: 15
      continuous:
        days: 14
      motion:
        days: 0
    notifications:
      enabled: true

    zones:
      cam2_person:
        coordinates: 0.808,1,0.374,1,0.56,0,0.58,0
        inertia: 3
        loitering_time: 0
        objects: person
    motion:
      mask: 0.584,0,0.812,0.998,0.995,0.995,1,0

# ----------------------------------------CAM 3 ------------------------------------

  cam3:
    review:
      alerts:
        required_zones: cam3_person
      detections:
        required_zones: cam3_person
    lpr:
      enabled: false
    ffmpeg:
      inputs:
        - path: rtsp://127.0.0.1:8554/cam3_sub
          input_args: preset-rtsp-restream
          roles:
            - detect
        - path: rtsp://127.0.0.1:8554/cam3
          input_args: preset-rtsp-restream
          roles:
            - record
      output_args:
        record: preset-record-generic-audio-aac
    detect:
      width: 1280
      height: 720
      fps: 5
    objects:
      track:
        - person
      mask: 0.539,0.003,0.732,1,0.996,0.995,0.996,0.008
    snapshots:
      required_zones:
        - cam3_person
      enabled: true
      timestamp: true
      bounding_box: true
      crop: true
      height: 500
      retain:
        default: 14
    record:
      enabled: true
      alerts:
        retain:
          days: 14
        pre_capture: 15
        post_capture: 15
      detections:
        retain:
          days: 14
        pre_capture: 15
        post_capture: 15
      continuous:
        days: 14
      motion:
        days: 0
    notifications:
      enabled: true

    zones:
      cam3_person:
        coordinates: 0.442,0,0.243,0.992,0.723,1,0.535,0.003
        inertia: 3
        loitering_time: 0
        objects: person
    motion:
      mask:
        - 0.627,0.032,0.631,0.079,0.971,0.077,0.972,0.034
        - 0.002,0.003,0.007,0.994,0.238,0.99,0.44,0.003

# ----------------------------------------CAM 4 ------------------------------------

  cam4:
    review:
      alerts:
        required_zones: cam4_person
      detections:
        required_zones: cam4_person
    lpr:
      enabled: false
    ffmpeg:
      inputs:
        - path: rtsp://127.0.0.1:8554/cam4_sub
          input_args: preset-rtsp-restream
          roles:
            - detect
        - path: rtsp://127.0.0.1:8554/cam4
          input_args: preset-rtsp-restream
          roles:
            - record
      output_args:
        record: preset-record-generic-audio-aac
    detect:
      width: 1280
      height: 720
      fps: 5
    objects:
      track:
        - person
      mask:
        - 0.67,1,0.996,0.992,0.997,0.006,0.302,0.001,0.366,0.538,0.52,0.496,0.575,0.468
        - 0.003,0.002,0,0.978,0.039,0.537,0.295,0.014
    snapshots:
      required_zones:
        - cam4_person
      enabled: true
      timestamp: true
      bounding_box: true
      crop: true
      height: 500
      retain:
        default: 14
    record:
      enabled: true
      alerts:
        retain:
          days: 14
        pre_capture: 15
        post_capture: 15
      detections:
        retain:
          days: 14
        pre_capture: 15
        post_capture: 15
      continuous:
        days: 14
      motion:
        days: 0
    notifications:
      enabled: true

    zones:
      cam4_person:
        coordinates: 
          0.045,0.541,0,0.998,0.664,1,0.572,0.493,0.501,0.513,0.364,0.545,0.299,0.016
        inertia: 3
        loitering_time: 0
        objects: person
    motion: {}

# ----------------------------------------CAM 5 ------------------------------------

  cam5:
    review:
      alerts:
        required_zones: cam5_person
      detections:
        required_zones: cam5_person
    lpr:
      enabled: false
    ffmpeg:
      inputs:
        - path: rtsp://127.0.0.1:8554/cam5_sub
          input_args: preset-rtsp-restream
          roles:
            - detect
        - path: rtsp://127.0.0.1:8554/cam5
          input_args: preset-rtsp-restream
          roles:
            - record
      output_args:
        record: preset-record-generic-audio-aac
    detect:
      width: 1280
      height: 720
      fps: 5
    objects:
      track:
        - person
      mask: 0,0,0,1,0.179,1,0.511,0
    snapshots:
      required_zones:
        - cam5_person
      enabled: true
      timestamp: true
      bounding_box: true
      crop: true
      height: 500
      retain:
        default: 14
    record:
      enabled: true
      alerts:
        retain:
          days: 14
        pre_capture: 15
        post_capture: 15
      detections:
        retain:
          days: 14
        pre_capture: 15
        post_capture: 15
      continuous:
        days: 14
      motion:
        days: 0
    notifications:
      enabled: true

    zones:
      cam5_person:
        coordinates: 
          0.521,0,0.456,0.185,0.383,0.42,0.308,0.639,0.193,1,0.811,0.997,0.568,0.005
        inertia: 3
        loitering_time: 0
        objects: person
    motion:
      mask: 0.566,0,0.816,0.998,0.999,0.995,0.998,0.005

# ----------------------------------------CAM 6 ------------------------------------

  cam6:
    review:
      alerts:
        required_zones: cam6_person
      detections:
        required_zones: cam6_person
    lpr:
      enabled: false
    ffmpeg:
      inputs:
        - path: rtsp://127.0.0.1:8554/cam6_sub
          input_args: preset-rtsp-restream
          roles:
            - detect
        - path: rtsp://127.0.0.1:8554/cam6
          input_args: preset-rtsp-restream
          roles:
            - record
      output_args:
        record: preset-record-generic-audio-aac
    detect:
      width: 1280
      height: 720
      fps: 5
    objects:
      track:
        - person
      filters:
        person:
          min_area: 3000
          max_area: 90000
      mask: 
        1,1,1,0,0.216,0,0.235,0.231,0.271,0.22,0.298,0.21,0.312,0.249,0.554,1
    snapshots:
      required_zones:
        - cam6_person
      enabled: true
      timestamp: true
      bounding_box: true
      crop: true
      height: 500
      retain:
        default: 14
    record:
      enabled: true
      alerts:
        retain:
          days: 14
        pre_capture: 15
        post_capture: 15
      detections:
        retain:
          days: 14
        pre_capture: 15
        post_capture: 15
      continuous:
        days: 14
      motion:
        days: 0
    notifications:
      enabled: true

    zones:
      cam6_person:
        coordinates: 
          0.215,0.016,0.131,0.333,0.075,1,0.543,0.988,0.296,0.222,0.232,0.245
        inertia: 3
        loitering_time: 0
        objects: person
    motion:
      mask: 0.002,0.003,0.005,0.997,0.069,0.997,0.128,0.321,0.212,0.002

# ----------------------------------------CAM 7 ------------------------------------

  cam7:
    review:
      alerts:
        required_zones: cam7_person
      detections:
        required_zones: cam7_person
    lpr:
      enabled: false
    ffmpeg:
      inputs:
        - path: rtsp://127.0.0.1:8554/cam7_sub
          input_args: preset-rtsp-restream
          roles:
            - detect
        - path: rtsp://127.0.0.1:8554/cam7
          input_args: preset-rtsp-restream
          roles:
            - record
      output_args:
        record: preset-record-generic-audio-aac
    detect:
      width: 1280
      height: 720
      fps: 5
    objects:
      track:
        - person
      mask: 0.616,0.003,0.756,0.445,0.866,0.99,0.994,0.997,0.996,0.006
    snapshots:
      required_zones:
        - cam7_person
      enabled: true
      timestamp: true
      bounding_box: true
      crop: true
      height: 500
      retain:
        default: 14
    record:
      enabled: true
      alerts:
        retain:
          days: 14
        pre_capture: 15
        post_capture: 15
      detections:
        retain:
          days: 14
        pre_capture: 15
        post_capture: 15
      continuous:
        days: 14
      motion:
        days: 0
    notifications:
      enabled: true

    zones:
      cam7_person:
        coordinates: 
          0.404,0,0.308,1,0.861,0.994,0.815,0.742,0.739,0.408,0.611,0.002
        inertia: 3
        loitering_time: 0
        objects: person
    motion:
      mask:
        - 0.001,0.003,0.004,0.992,0.303,0.997,0.398,0.005
        - 0.629,0.03,0.633,0.074,0.97,0.079,0.971,0.032

# ----------------------------------------CAM 8 ------------------------------------

  cam8:
    review:
      alerts:
        required_zones: cam8_person
      detections:
        required_zones: cam8_person
    lpr:
      enabled: false
    ffmpeg:
      inputs:
        - path: rtsp://127.0.0.1:8554/cam8_sub
          input_args: preset-rtsp-restream
          roles:
            - detect
        - path: rtsp://127.0.0.1:8554/cam8
          input_args: preset-rtsp-restream
          roles:
            - record
      output_args:
        record: preset-record-generic-audio-aac
    detect:
      width: 1280
      height: 720
      fps: 5
    objects:
      track:
        - person
      filters:
        person:
          min_area: 5000
          max_area: 90000
      mask: 
        0.279,0.01,0.342,0.604,0.67,0.801,0.634,0.944,0.62,0.997,0.996,0.995,0.995,0.003
    snapshots:
      required_zones:
        - cam8_person
      enabled: true
      timestamp: true
      bounding_box: true
      crop: true
      height: 500
      retain:
        default: 14
    record:
      enabled: true
      alerts:
        retain:
          days: 14
        pre_capture: 15
        post_capture: 15
      detections:
        retain:
          days: 14
        pre_capture: 15
        post_capture: 15
      continuous:
        days: 14
      motion:
        days: 0
    notifications:
      enabled: true

    zones:
      cam8_person:
        coordinates: 0.042,0.612,0.174,0.99,0.62,0.997,0.671,0.798,0.155,0.499
        inertia: 3
        loitering_time: 0
        objects: person
    motion:
      mask: 0.629,0.027,0.634,0.08,0.972,0.08,0.972,0.03

# ----------------------------------------CAM 9 ------------------------------------

  cam9:
    lpr:
      enabled: false
    ffmpeg:
      inputs:
        - path: rtsp://127.0.0.1:8554/cam9_sub
          input_args: preset-rtsp-restream
          roles:
            - detect
        - path: rtsp://127.0.0.1:8554/cam9
          input_args: preset-rtsp-restream
          roles:
            - record
      output_args:
        record: preset-record-generic-audio-aac
    detect:
      width: 1280
      height: 720
      fps: 5
    objects:
      track:
        - person
      filters:
        person:
          min_area: 5000
          max_area: 90000
    snapshots:
      required_zones:
        - cam9_person
      enabled: true
      timestamp: true
      bounding_box: true
      crop: true
      height: 500
      retain:
        default: 14
    record:
      enabled: true
      alerts:
        retain:
          days: 14
        pre_capture: 15
        post_capture: 15
      detections:
        retain:
          days: 14
        pre_capture: 15
        post_capture: 15
      continuous:
        days: 14
      motion:
        days: 0
    notifications:
      enabled: true

    motion:
      mask: 0.627,0.032,0.628,0.079,0.971,0.082,0.974,0.032
    zones:
      cam9_person:
        coordinates: 
          0.123,0.587,0.374,1,0.562,1,0.824,0.018,0.488,0.01,0.324,0.253
        loitering_time: 0
        objects: person
version: 0.17-0


semantic_search:
  enabled: true
  model_size: small
face_recognition:
  enabled: false
  model_size: small
lpr:
  enabled: false
classification:
  bird:
    enabled: false
notifications:
  enabled: true
  email: dp@p2pnode.org

```

<details id="bkmrk-new-config-mqtt%3A-ena"><summary>New Config</summary>

```yaml
mqtt:
  enabled: true

semantic_search:
  enabled: true
  reindex: false

objects:
  track:
    - person
    - car
  filters:
    person:
      min_score: .60
      threshold: .65
    car:
      min_score: .60
      threshold: .65



cameras:     # No cameras defined, UI wizard should be used
  cam_1:
    enabled: true
    ffmpeg:
      inputs:
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.101:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
          roles:
            - record
            - audio
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.101:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
          roles:
            - detect
    detect:
      width: 1280
      height: 720
    record:
      enabled: true
      continuous:
        days: 14
    live:
      streams:
        Stream 1: cam_1_1
        Stream 2: cam_1_2
    notifications:
      enabled: true
    zones:
      cam_1_person:
        coordinates: 
          0.596,0.09,0.523,0.089,0,0.549,0,1,0.111,1,0.607,0.985,0.652,0.097
        inertia: 3
        loitering_time: 0
        objects: person
  cam_2:
    enabled: true
    ffmpeg:
      inputs:
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.102:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
          roles:
            - record
            - audio
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.102:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
          roles:
            - detect
    detect:
      width: 1280
      height: 720
    record:
      enabled: true
      continuous:
        days: 14
    live:
      streams:
        Stream 1: cam_2_1
        Stream 2: cam_2_2
    notifications:
      enabled: true
    zones:
      cam_2_person:
        coordinates: 0.483,0.265,0.35,0.998,0.754,0.992,0.582,0.009
        loitering_time: 0
        objects: person
  cam_3:
    enabled: true
    ffmpeg:
      inputs:
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.103:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
          roles:
            - record
            - audio
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.103:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
          roles:
            - detect
    detect:
      width: 1280
      height: 720
    live:
      streams:
        Stream 1: cam_3_1
        Stream 2: cam_3_2
    zones:
      cam_3_person:
        coordinates: 0.497,0.106,0.59,0.991,0.462,0.992,0.45,0.13
        loitering_time: 0
        objects: person
  cam_4:
    enabled: true
    ffmpeg:
      inputs:
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.104:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
          roles:
            - record
            - audio
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.104:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
          roles:
            - detect
    detect:
      width: 1280
      height: 720
    record:
      enabled: true
      continuous:
        days: 14
    live:
      streams:
        Stream 1: cam_4_1
        Stream 2: cam_4_2
    notifications:
      enabled: true
    zones:
      cam_4_person:
        coordinates: 0.593,0.465,0.712,0.994,0.366,0.997,0.374,0.466
        loitering_time: 0
        objects: person
  cam_5:
    enabled: true
    ffmpeg:
      inputs:
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.105:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
          roles:
            - record
            - audio
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.105:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
          roles:
            - detect
    detect:
      width: 1280
      height: 720
    record:
      enabled: true
      continuous:
        days: 14
    live:
      streams:
        Stream 1: cam_5_1
        Stream 2: cam_5_2
    notifications:
      enabled: true
    zones:
      cam_5_person:
        coordinates: 0.534,0.116,0.517,0.991,0.332,0.998,0.491,0.113
        loitering_time: 0
        objects: person
  cam_6:
    enabled: true
    ffmpeg:
      inputs:
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.106:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
          roles:
            - record
            - audio
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.106:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
          roles:
            - detect
    detect:
      width: 1280
      height: 720
    record:
      enabled: true
      continuous:
        days: 14
    live:
      streams:
        Stream 1: cam_6_1
        Stream 2: cam_6_2
    notifications:
      enabled: true
    zones:
      cam_6_person:
        coordinates: 0.225,0.198,0.279,0.593,0.346,0.998,0.489,1,0.253,0.166
        loitering_time: 0
        objects: person
  cam_7:
    enabled: true
    ffmpeg:
      inputs:
        - path: rtsp://127.0.0.1:8554/cam_7_1
          input_args: preset-rtsp-restream
          roles:
            - record
            - audio
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.107:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
          roles:
            - detect
    detect:
      width: 1280
      height: 720
    record:
      enabled: true
      continuous:
        days: 14
    live:
      streams:
        Stream 1: cam_7_1
        Stream 2: cam_7_2
    notifications:
      enabled: true
    zones:
      cam_7_person:
        coordinates: 0.519,0.071,0.603,0.991,0.806,0.991,0.595,0.027
        loitering_time: 0
        objects: person
  cam_8:
    enabled: true
    ffmpeg:
      inputs:
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.108:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
          roles:
            - record
            - audio
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.108:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
          roles:
            - detect
    detect:
      width: 1280
      height: 720
    record:
      enabled: true
      continuous:
        days: 14
    live:
      streams:
        Stream 1: cam_8_1
        Stream 2: cam_8_2
    notifications:
      enabled: true
    zones:
      cam_8_person:
        coordinates: 
          0.287,0.585,0.092,0.753,0.126,0.887,0.19,1,0.356,0.931,0.477,0.694
        loitering_time: 0
        objects: person
  cam_9:
    enabled: true
    ffmpeg:
      inputs:
        - path: rtsp://127.0.0.1:8554/cam_9_1
          input_args: preset-rtsp-restream
          roles:
            - record
            - audio
        - path: 
            rtsp://admin:Stel13DeternetArea1()@10.131.2.109:554/cam/realmonitor?channel=1&subtype=1
          roles:
            - detect
    detect:
      width: 1280
      height: 720
    record:
      enabled: true
      continuous:
        days: 14
    live:
      streams:
        Stream 1: cam_9_1
        Stream 2: cam_9_2
    notifications:
      enabled: true
    zones:
      cam_9_person:
        coordinates: 0.362,0.184,0.703,0.52,0.554,0.971,0.365,0.973,0.128,0.588
        loitering_time: 0
        objects: person
version: 0.17-0
go2rtc:
  streams:
    cam_1_1:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.101:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
    cam_1_2:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.101:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
    cam_2_1:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.102:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
    cam_2_2:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.102:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
    cam_3_1:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.103:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
    cam_3_2:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.103:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
    cam_4_1:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.104:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
    cam_4_2:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.104:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
    cam_5_1:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.105:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
    cam_5_2:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.105:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
    cam_6_1:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.106:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
    cam_6_2:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.106:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
    cam_7_1:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.107:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
    cam_7_2:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.107:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
    cam_8_1:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.108:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
    cam_8_2:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.108:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
    cam_9_1:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.109:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
    cam_9_2:
      - rtsp://admin:Stel13DeternetArea1()@10.131.2.109:554/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif
notifications:
  enabled: true
  email: dp@p2pnode.org

```

</details>

# 02. Configure Cameras

**Camera Network**

The first thing to be made sure of is to create a dedicated network for your camera system. This can either be dedicated or VLAN based. In this way you can separate Camera traffic from other traffic and if your camera netwok gets breached than all other services will not be affected. Depending on your network setup you can either define this VLAN directly on an L3 swich or if you use the router on a stick model on your router. Hence, make sure all cameras are on the same CAM network.

**Initial Camera Setup**

Now, by default your cameras are not yet living on the camera network VLAN that we just created. Now, for each brand and camera it is different but it basically boils down to this.

1. Make sure you have a laptop with an ethernet port
2. Look up on the internet how you can reset your particular camera to its default settings.
3. This will most likely also tell you what the default IP address is that particular camera e.g Amcrest cameras live on 192.168.1.108.
4. If you know that then you also know on which network it lives.
5. Next, we need to set our laptop to the same default network as the camera.
6. Then we can simply access the camera by typing in the address of the camera in our favourite webbrowser.
7. Then again depending on your camera, go to the networking page to give your camera a static IP address on the Camera Network.
8. Note! Once you change the ip address of the camera then you can only keep accessing it if you bring your laptop on that network as well.
9. After you have done that you can stick the IP camera in an untagged CAM Network port on your PoE switch.
10. If you can then connect to it with your laptop by connected it as well to the same switch then you know it works!
11. Repeat this process until you brought all the cameras on the camera network.

**Streams**

Next up are the camera stream possibilities of your camera. Most cameras come at least with two camera streams. These streams are basically recording the same thing but on different resolution scales. For instance, for your recordings you would love to have the highest resolution possible, howerver for your object and sound detection you don't need that. This can greatly reduce the stress on your resources and hence provide a much smoother experience, especially on systems that are not so well resourced.

Other that we also need to know or set the resolution of all of the cameras. The reason being is that these resolutions should be the same as in our Frigate configuration file later on. It is all up to you and the resources but some common resolutions would be

1. 640x480 (VGA) for substream (The higher the sream the more stress will be put on your resources)
2. Highest resolution for main stream (e.g 1920x1080 or 2960x1668)

Make sure you write these numbers down and have set them all the same for all your cameras.

**NTP Time Server**

An NTP server (Network Time Protocol server) is a server that provides accurate time information to clients over the Internet, allowing them to synchronize their clocks to Coordinated Universal Time (UTC) with high precision. NTP servers can maintain time accuracy within a few milliseconds over local networks and tens of milliseconds over the public Internet.

Now why would you want this ? Well you want that each camera in your system displays the same time i.e that all clocks are synchronized. They even synchronize with summer and winter times ;) This is a must have instead of cameras showing different times.

Now, which NTP servers to use then ? Well I would recommend to use the NTP servers from the [NTP Pool Project](https://www.ntppool.org/en/). The pool.ntp.org project is a big virtual cluster of timeservers providing reliable, [easy to use](https://www.ntppool.org/en/use.html) NTP service for millions of clients. You could click on your continent region and then use any of the time servers they provide. For instance clicking on Europe you get the following addresses

<p class="callout info">server 0.europe.pool.ntp.org  
server 1.europe.pool.ntp.org  
server 2.europe.pool.ntp.org  
server 3.europe.pool.ntp.org</p>

You can use any of these 4 and implement them as the NTP server for each camera. Make sure to use the same s.t they all use the same time servers and are synchronized.

**Viewing Preferences**

Now, depnding on the camera you have obtained they all have different possibilities. It is now then time to go to the cameras and tweak it to your liking. For instance, if you prefer night vision with colour on your camera's then you can set that setting for your camera. I would highly recommend to do this ;)

# 01. Hardware Pass Through

To make frigate operate smoothly and effectively a GPU or XXX should be used for hardware acceleration. Otherwise all the image recognition and playback needs to be handled by the CPU which is really heavy. If you don't do this and you have a bunch of cameras then it can easily consume 8 cpu cores if not more. Hence, get a GPU or Google XXX device.

1. Inside of the BIOS of your system go to

Tutorial on Hardware Acceleration for Frigate: [https://www.youtube.com/watch?v=SeHgsIwyOuY](https://www.youtube.com/watch?v=SeHgsIwyOuY)

1\. Then Resizable BAR needs to be turned on in the BIOS of your system if it's available.

2\. Then go int

# 3. Mount NFS Share

# 04. Mount NFS Share to Linux VM

1. Create dataset
2. Data space management -&gt; set it to x TiB
3. Shares -&gt; Unix -&gt; Add

!!!! Mount should happen at root !!!!!

Now, that we have created an NFS share it is time to share it with another machine virtual or bare metal. In this case we will install inside a linux VM

To test if a TrueNas NFS share can be mounted use the following command:

```
sudo mount -t nfs 10.131.1.10:/mnt/alexandria/frigate /home/dpasnfrigate/media
```

```
sudo mount -t nfs 10.131.1.10:/mnt/alexandria/frigate /home/dpasnfrigate/media
```

# Keep NFS share Mounted on Reboots

Generally, you will want to mount the remote NFS directory automatically when the system boots.

The /etc/fstab file contains a list of entries that define where how and what filesystem will be mounted on system startup.

To automatically mount an NFS share when your Linux system starts up add a line to the /etc/fstab file. The line must include the hostname or the IP address of the NFS server, the exported directory, and the mount point on the local machine.

Use the following procedure to automatically mount an NFS share on Linux systems:

1. Set up a mount point for the remote NFS share:

```
sudo mkdir /frigate/media
```

```
sudo mkdir /frigate/media
```

2. Open the /etc/fstab file with your text editor :

```
sudo nano /etc/fstab
```

```
sudo nano /etc/fstab
```

3. Add the following line

```
10.131.2.10:/mnt/alexandria/frigate frigate/media  nfs defaults 0 0
```

```
10.131.2.10:/mnt/alexandria/frigate frigate/media  nfs defaults 0 0
```

4. it
5. Finally you need to update the new file with

```
systemctl daemon-reload
```

```
systemctl daemon-reload
```

6. Run the mount command in one of the following forms to mount the NFS share:

```
mount frigate/media
```

```
mount frigate/media
```

7. The mount command, will read the content of the /etc/fstab and mount the share.
8. Next time you reboot the system the NFS share will be mounted automatically.

admin  
60ab1406fba90830c0126bbdcae06743d54a4f62d76f1e75

sudo apt install gnome-software-plugin-flatpak

# 1.5.16 OpenLift

# 1.5.17 Arr Stack

<span>In this chapter we follow roughly the guidelines from </span>[Techhut Instruction Video](https://www.youtube.com/watch?v=twJDyoj0tDc)<span> and the Trash Guides guide. However, there are other methods as well of course.</span>

# 01. Architectural Overview

[![Screenshot From 2026-06-15 17-51-08.png](https://docs.rfeyn.org/uploads/images/gallery/2026-07/scaled-1680-/cUl52tVXBuoOHEKY-screenshot-from-2026-06-15-17-51-08-png.png)](https://docs.rfeyn.org/uploads/images/gallery/2026-07/scaled-1680-/cUl52tVXBuoOHEKY-screenshot-from-2026-06-15-17-51-08-png.png)

##### Movie/Show Request

1. A user makes a request via Seerr, which is basically a catalogue of all the existing movies and tv shows and upcoming ones. This is where the end user will interact with for requests. Everything else from 2-4 is not publicly accessible. Only 1 and 5 are in the whole process.
2. Then the request will end up in Radarr for movies and Sonarr for TV shows.
3. Radarr and Sonarr are open-source applications designed for automating the downloading of movies and TV shows, respectively. They help users track their favorite media, automatically search for new episodes or films, and manage downloads through a user-friendly web interface.

##### Overview of the Request Process

Radarr/Sonarr and Prowlarr work in tandem to automate the downloading of movies. Here’s how the process unfolds:

1. <span class="font-semibold">Search Request</span>: Radarr/Sonarr initiates a search request for a specific movie/show.
2. <span class="font-semibold">Querying Indexers</span>: Prowlarr receives this request and queries all its configured indexers.
3. <span class="font-semibold">Returning Results</span>: The results from the indexers are sent back to Prowlarr.
4. <span class="font-semibold">Final Decision</span>: Prowlarr then forwards these results back to Radarr/Sonarr, which makes the final decision on which movie/show/episode to download.

##### Download clients

1. After the correct movie/show has been confirmed depending on if its a usenet or torrent file is then send to one of the download clients they are connected to.
2. Examples of these download clients are nzbget for usenet and qbittorrent for torrents.
3. They go out and download the movies/shows to your hard drives

##### Front end Jellyfin Clients

List of all [Jellyfin clients](https://docs.rfeyn.org/books/16-shapps/page/jellyfin-clients)

Then finally you have multiple front ends that users can interact with to actually watch their movies and shows. Basically Jellyfin sits in the backend and any application that can speak to the Jellyfin API can represent this media how they seem fit. Famous ones I like are

1. Fladder for Android Mobile and Laptops (It allows Seerr to be integrated into one application)
2. Jellyfin for TV
3. Kodi with a sweet theme for the TV
4. For iOS devices I would recommend

# 03. Mount NFS Share inside Arr VM

Now, that we have created an NFS share we should mount it inside the VM. But before we can mount it we need to install the NFS tools such that it can talk the NFS langauge. This is fairly straightforward with the following commands

1\. Within the VM install `cifs-utils`

```
sudo apt install cifs-utils
```

2\. Now, edit the `fstab` file and add the following lines editing them to match your information:

```
sudo nano /etc/fstab
```

<div class="zeroclipboard-container" id="bkmrk-3.-then-in-here-you-">3. Then in here you will specify your NFS share. It is fairly simple </div><div class="zeroclipboard-container" id="bkmrk-%C2%A0"> </div><div class="zeroclipboard-container" id="bkmrk-"></div><div class="zeroclipboard-container" id="bkmrk--1"></div><div class="zeroclipboard-container" id="bkmrk--2"></div>```
IP Address arr VM:/mnt/pool/dataset_name /mnt/data  nfs defaults 0 0
```

4\. Once that is saved we restart the daemon and mount the file share

```bash
sudo systemctl daemon-reload
sudo mount -a
```

5\.

# 02. Creating a NFS Share

Since this stack will save lots of big files i.e movies and tv shows we will create an NFS share for this on our TrueNas VM. You don't need to use TrueNas obviously to create an NFS share but this guide uses TrueNas and hence we do that ;)

1\. First we will create a new dataset in TrueNas

2\. Go to Datasets -&gt; Click on Add Dataset

3\. Give it a name you like

4\. Leave the Dataset Preset to Generi

5\. Create the dataset ;)

6\. Once that is done we click on the dataset and we need to change its permissions

7\. Edit the permissions and make sure that the User 1000 has the read write and Execute permissions on both the User and Group section. Leave all the other boxes for Other unchecked.

8\. Sweet! Then finally we will make an NFS share that our Arr Stack will utilize to download and store content on.

9\. Click on Shares -&gt; NFS -&gt; Add

10\. Then give it a name and choose the dataset for your Arr Stack.

11\. For now you can leave the networks and hosts as it is. We can later restrict it by only allowing the Arr stack access to it but that's for later.

12\. Cheers!! you made the Arr Stack NFS share !

Awesome, Let's now look at the folder structure ;)

# 04. Folder Structure

It's good practice to give all containers the same access to the same root directory or share. This is why all containers in the compose file have the bind volume mount `/data:/data`. It makes everything easier, plus passing in two volumes such as the commonly suggested `/tv`, `/movies`, and `/downloads` makes them look like two different file systems, even if they are a single file system outside the container. See my current setup below.

```
data
├── books
├── downloads
│   ├── qbittorrent
│   │   ├── completed
│   │   ├── incomplete
│   │   └── torrents
│   └── nzbget
│       ├── completed
│       ├── intermediate
│       ├── nzb
│       ├── queue
│       └── tmp
├── movies
├── music
├── shows
└── youtube
```

1\. Now, to implement this we will move into our NFS share inside our VM and create the above folder structure with the command

```bash
mkdir -p downloads/qbittorrent/{completed,incomplete,torrents} && mkdir -p downloads/nzbget/{completed,intermediate,nzb,queue,tmp}
```

2\. Perfect! You can check with "ls" if the folder structure was actually created correctly.

3\. Now, to get the permissions right we need to move back into **TrueNas** to have the ownership of the folders recursively owned by user 1000 and group 1000.

4\. Go to TrueNas -&gt; Datasets -&gt; DATASET\_NAME -&gt; Click on Permissions

5\. In here make sure that the 6 top blocks are all set and that you check the boxes

- [x] Apply User
- [x] Apply Group
- [x] Apply permissions recursively.

6\. Then accept the Warning and save the permission. Sweet! now you are ready to start setting up the docker compose file and can be sure that all the containers have the proper permissions to all the folders.

# 05. Creating the Docker Compose file

Now, that the NFS share and folder structure is created and added to the Virtual machine with /etc/fstab we can start creating the docker compose file and its environment ".env" file. It must be said that this docker compose file is basically a copy paste from the compose file created by home lab teacher Techhut. You can find his compose file [here](https://github.com/TechHutTV/homelab/blob/main/media/jellyfin/compose.yaml). In this docker page I will first explain all the different components and what they do. However, you can also directly copy and paste docker compose and environment file if you want of course.

<details id="bkmrk-docker-compose-file-"><summary>Docker Compose File</summary>

```yaml
networks:
  servarrnetwork:
    name: servarrnetwork
    ipam:
      config:
        - subnet: 172.39.0.0/24
services:
  gluetun:
    image: qmcgaw/gluetun
    container_name: gluetun
    cap_add:
      - NET_ADMIN
    devices:
      - /dev/net/tun:/dev/net/tun # If running on an LXC see readme for more info.
    networks:
      servarrnetwork:
        ipv4_address: ${SET_IP_GLUETUN}
    ports:
      - 8080:8080 # qbittorrent web interface
      - 6881:6881 # qbittorrent torrent port
      - 6789:6789 # nzbget
      - 9696:9696 # prowlarr
      - 8191:8191 # flaresolverr
    volumes:
      - ./gluetun:/gluetun
    # Make a '.env' file in the same directory.
    env_file:
      - .env
    healthcheck:
      test: ping -c 1 www.google.com || exit 1
      interval: 20s
      timeout: 10s
      retries: 5
    restart: unless-stopped
  qbittorrent:
    image: lscr.io/linuxserver/qbittorrent:latest
    container_name: qbittorrent
    restart: unless-stopped
    labels:
      - deunhealth.restart.on.unhealthy=true
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
      - WEBUI_PORT=8080 # must match "qbittorrent web interface" port number in gluetun's service above
      - TORRENTING_PORT=${FIREWALL_VPN_INPUT_PORTS} # airvpn forwarded port, pulled from .env
    volumes:
      - ./qbittorrent:/config
      - ${ROOT_DIR}:/data
    depends_on:
      gluetun:
        condition: service_healthy
        restart: true
    network_mode: service:gluetun
    healthcheck:
      test: ping -c 1 www.google.com || exit 1
      interval: 60s
      retries: 3
      start_period: 20s
      timeout: 10s
  # See the 'qBittorrent Stalls with VPN Timeout' section for more information.
  deunhealth:
    image: qmcgaw/deunhealth
    container_name: deunhealth
    network_mode: none
    environment:
      - LOG_LEVEL=info
      - HEALTH_SERVER_ADDRESS=127.0.0.1:9999
      - TZ=${TZ}
    restart: always
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
  nzbget:
    image: lscr.io/linuxserver/nzbget:latest
    container_name: nzbget
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ./nzbget:/config
      - ${ROOT_DIR}:/data
    depends_on:
      gluetun:
        condition: service_healthy
        restart: true
    restart: unless-stopped
    network_mode: service:gluetun
  prowlarr:
    image: lscr.io/linuxserver/prowlarr:latest
    container_name: prowlarr
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ./prowlarr:/config
    restart: unless-stopped
    depends_on:
      gluetun:
        condition: service_healthy
        restart: true
    network_mode: service:gluetun
  flaresolverr:
    image: ghcr.io/flaresolverr/flaresolverr:latest
    container_name: flaresolverr
    environment:
      - LOG_LEVEL=${LOG_LEVEL:-info}
      - LOG_HTML=${LOG_HTML:-false}
      - CAPTCHA_SOLVER=${CAPTCHA_SOLVER:-none}
      - TZ=${TZ}
    depends_on:
      gluetun:
        condition: service_healthy
        restart: true
    network_mode: service:gluetun
    restart: unless-stopped
  sonarr:
    image: lscr.io/linuxserver/sonarr:latest
    container_name: sonarr
    restart: unless-stopped
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ./sonarr:/config
      - ${ROOT_DIR}:/data
    ports:
      - 8989:8989
    networks:
      servarrnetwork:
        ipv4_address: ${SET_IP_SONARR}
  radarr:
    image: lscr.io/linuxserver/radarr:latest
    container_name: radarr
    restart: unless-stopped
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ./radarr:/config
      - ${ROOT_DIR}:/data
    ports:
      - 7878:7878
    networks:
      servarrnetwork:
        ipv4_address: ${SET_IP_RADARR}
  lidarr:
    container_name: lidarr
    image: lscr.io/linuxserver/lidarr:latest
    restart: unless-stopped
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ./lidarr:/config
      - ${ROOT_DIR}:/data
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    ports:
      - 8686:8686
    networks:
      servarrnetwork:
        ipv4_address: ${SET_IP_LIDARR}
  bazarr:
    image: lscr.io/linuxserver/bazarr:latest
    container_name: bazarr
    restart: unless-stopped
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ./bazarr:/config
      - ${ROOT_DIR}:/data
    ports:
      - 6767:6767
    networks:
      servarrnetwork:
        ipv4_address: ${SET_IP_BAZARR}
  seerr:
    container_name: seerr
    image: ghcr.io/seerr-team/seerr:latest
    environment:
      - LOG_LEVEL=debug
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    healthcheck:
      test: wget --no-verbose --tries=1 --spider http://localhost:5055/api/v1/status
        || exit 1
      start_period: 20s
      timeout: 3s
      interval: 15s
      retries: 3
    restart: unless-stopped
    volumes:
      - ./seerr:/app/config
    ports:
      - 5055:5055
    networks:
      servarrnetwork:
        ipv4_address: ${SET_IP_SEERR}
  # jellystat-db:
  #   image: postgres:18.1
  #   container_name: jellystat-db
  #   restart: unless-stopped
  #   shm_size: '1gb'
  #   environment:
  #     - POSTGRES_USER=${JELLYSTAT_POSTGRES_USER}
  #     - POSTGRES_PASSWORD=${JELLYSTAT_POSTGRES_PASSWORD}
  #   volumes:
  #     - ./jellystat/postgres-data:/var/lib/postgresql/data
  #   healthcheck:
  #     test: ["CMD-SHELL", "pg_isready --dbname=postgres --username=${JELLYSTAT_POSTGRES_USER}"]
  #     interval: 10s
  #     timeout: 5s
  #     retries: 5
  #   networks:
  #     servarrnetwork:
  #       ipv4_address: ${SET_IP_JELLYSTAT_DB}
  #
  # jellystat:
  #   image: cyfershepard/jellystat:latest
  #   container_name: jellystat
  #   restart: unless-stopped
  #   environment:
  #     - POSTGRES_USER=${JELLYSTAT_POSTGRES_USER}
  #     - POSTGRES_PASSWORD=${JELLYSTAT_POSTGRES_PASSWORD}
  #     - POSTGRES_IP=jellystat-db
  #     - POSTGRES_PORT=5432
  #     - JWT_SECRET=${JELLYSTAT_JWT_SECRET}
  #     - TZ=${TZ}
  #   volumes:
  #     - ./jellystat/backup-data:/app/backend/backup-data
  #   ports:
  #     - 3000:3000
  #   depends_on:
  #     jellystat-db:
  #       condition: service_healthy
  #   healthcheck:
  #     test: wget --no-verbose --tries=1 --spider http://localhost:3000/auth/isConfigured || exit 1
  #     interval: 60s
  #     timeout: 30s
  #     retries: 5
  #     start_period: 30s
  #   networks:
  #     servarrnetwork:
  #       ipv4_address: ${SET_IP_JELLYSTAT}

```

</details><details id="bkmrk-environment-variable"><summary>Environment Variables</summary>

```yaml
# General UID/GID and Timezone
TZ=America/Los_Angeles
PUID=1000
PGID=1000

# Input your VPN provider and type here
VPN_SERVICE_PROVIDER=airvpn
VPN_TYPE=wireguard

# Mandatory, airvpn forwarded port
FIREWALL_VPN_INPUT_PORTS=port

# Copy all these variables from your generated configuration file
WIREGUARD_PUBLIC_KEY=key
WIREGUARD_PRIVATE_KEY=key
WIREGUARD_PRESHARED_KEY=key
WIREGUARD_ADDRESSES=ip

# Optional location variables, comma separated list, no spaces after commas, make sure it matches the config you created
# NOTE: These can cause connection failures with some providers. Remove or comment out if Gluetun won't connect.
#SERVER_COUNTRIES=country
#SERVER_CITIES=city

# Health check duration
HEALTH_VPN_DURATION_INITIAL=120s

# Static IPs for services on servarrnetwork
SET_IP_GLUETUN=172.39.0.2
SET_IP_SONARR=172.39.0.3
SET_IP_RADARR=172.39.0.4
SET_IP_LIDARR=172.39.0.5
SET_IP_BAZARR=172.39.0.6
SET_IP_SEERR=172.39.0.7
SET_IP_JELLYSTAT_DB=172.39.0.8
SET_IP_JELLYSTAT=172.39.0.9

# Jellystat (uncomment service block in compose.yaml to enable)
JELLYSTAT_POSTGRES_USER=postgres
JELLYSTAT_POSTGRES_PASSWORD=changeme
JELLYSTAT_JWT_SECRET=changeme
```

</details>
##### Network

1. First of all an internal docker network is created called "servarrnetwork"
2. Then we give this network as well a subnet in a /24. This can be any private subnet you please since it is only internal


### Gluetun

So what does this docker compose file represent ? What is the workflow here ?

# 06. qBittorent

In this section we will setup our qBittorrent downloading client.

1\. First get your temporary password that is provided to login which you can find in the logs. Use the command

```bash
sudo docker logs qbittorrent
```

<details id="bkmrk-qbittorent-first-tim"><summary>Example output</summary>

\[migrations\] started  
\[migrations\] no migrations found  
───────────────────────────────────────

 ██╗ ███████╗██╗ ██████╗  
 ██║ ██╔════╝██║██╔═══██╗  
 ██║ ███████╗██║██║ ██║  
 ██║ ╚════██║██║██║ ██║  
 ███████╗███████║██║╚██████╔╝  
 ╚══════╝╚══════╝╚═╝ ╚═════╝

 Brought to you by linuxserver.io  
───────────────────────────────────────

To support LSIO projects visit:  
https://www.linuxserver.io/donate/

───────────────────────────────────────  
GID/UID  
───────────────────────────────────────

User UID: 1000  
User GID: 1000  
───────────────────────────────────────  
Linuxserver.io version: 5.2.1\_v2.0.13-ls460  
Build-date: 2026-06-08T23:02:32+00:00  
───────────────────────────────────────  
   
\[custom-init\] No custom files found, skipping...  
WebUI will be started shortly after internal preparations. Please wait...

\*\*\*\*\*\*\*\* Information \*\*\*\*\*\*\*\*  
To control qBittorrent, access the WebUI at: http://localhost:8080  
The WebUI administrator username is: admin  
The WebUI administrator password was not set. A temporary password is provided for this session: yfUHUIHFX  
You should set your own password in program preferences.  
Connection to localhost (::1) 8080 port \[tcp/http-alt\] succeeded!

</details>2\. Then go to IP address:8080 and login with "admin" and your temporary password  
3\. Once logged in you can change your password and username by going to Settings &gt; WebUI

4\.

  
5\. What's next is setting up the directory scheme for the torrent files  
6\. Go to Settings &gt; Downloads  
7\. Then Look for

Default save path: /data/torrents/completed   
Keep incomplete torrents in: /data/torrents/incomplete   
Copy torrent files to: /data/torrents/torrents

8\. Congratz now your qBittorent client is all set

# 07. NZBGet

For a Usenet downloading client we choose NZBget. Yes this is not the only one out there but it is leightweight and efficient. If your container is up and running you can find your NZB instance at

IP address VM:6789

1. Now, the first time that you will login you will need the standard login credentials which are

Default credentials:

Username: nzbget  
Password: tegbzn6789

2. As with any platform we first change the user credentials. Go to Settings &gt; Security &gt; Change username and Password

### Download Folders

1. Next we will setup up the download folders nzbget will use for its downloads. We already configured them in our folder structure so that will be a piece of cake
2. For this go to Settings &gt; Paths

In here we will specify

Main Dir: /data/usenet/  
DestDir: /data/usenet/completed  
InterDir: /data/usenet/incompleted

3. This is again according to the Trash Guide folder structure we created in the beginning. If you then hit Save and Apply it should give you no errors. If nzbget cannot reach the folders for writing permissions or they don't exist then it will tell you with a red banner.

### News-Server

1. Now, we will setup our new server. It is up to you which news server you choose however regardless you will need 3 items. Your username, password and the host URL. If you have obtained these credentials by login in to you news reader then you can go to Settings &gt; News-Server

- Fill in a name for the News-server
- Fill in the username
- Fill in the password
- Fill in the host URL

2. By hitting save and apply everything should be good if you did not receive any errors.
3. Aweseom then your downloading clients are set and we can move on

### Categories

Now, we have created the folders movies, tv, books and music inside the completed usenet folder. We now need to tell nzbget about these locations through the means of categories.

1. Go to Settings &gt; Categories
2. Add the Categories movies, tv, books and music. Make sure it is all in lower case ;)

##### NZBGET Health

**Health**  
A decreasing health for a movie in NZBGet typically indicates that the files are becoming less available or are missing parts, making it difficult to download them successfully. This can happen due to content takedowns or the age of the files, leading to failed downloads

**Extraction**  
Files need to be extracted from .rar archives in NZBGet because they are compressed to save space and facilitate faster downloads. Extracting them allows you to access the original files contained within the archive

# 08. Radarr

### 1. Create Account

Now, that we have setup our Download clients i.e qBittorent and NZBGet we will configure Radarr, Sonarr, Lidarr, Bazaarr. However, we will only demonstrate one of the 4 since the configuration is exactly the same

1. Go to your Radarr's IP address :7878
2. Once, there you will start making an account. For this you can again use Bitwarden to create random login credentials for your instance

### 2. Media Management

1. in this step we will assign the folders in which the radarr files will reside
2. Go to Settings &gt; Media Management &gt; Add root folder
3. Here you will choose the movie folder you have created in your docker compose file. If you follow this guide this would be at **/data/media/Movies**
4. Congratulations, now you have told Radarr where to store all the movies.

### 3. Downloading Clients

Now we will connect the downloading clients qBittorent and nzbget to Radarr for it to use.

1. Go to Settings &gt; Downloading Clients &gt; + add
2. Select qBittorent and fill in the credentials of your qBittorent downloading client
3. Once done, add another client but this time choose for nzbget.
4. Also fill in here the credentials of your nzbget client with the category movies
5. Awesome you are all set !

### 4. Indexers

The final thing we need to setup for our Radarr instance are indexers. However, we will use Prowlarr for this as a centralised indexer for all ARR apps. The only thing we need for Prowlarr to  
connect to Radarr is it's API key.

1. Go to Settings &gt; General
2. Copy paste the API key

# 09. Sonarr

### 1. Create Account

For Sonarr it will be quite similar as for Radarr

1. Go to your Radarr's IP address:**8989**
2. Once, there you will start making an account. For this you can again use Bitwarden to create random login credentials for your instance

### 2. Media Management

1. in this step we will assign the folders in which the radarr files will reside
2. Go to Settings &gt; Media Management &gt; Add root folder
3. Here you will choose the movie folder you have created in your docker compose file. If you follow this guide this would be at **/data/media/tvshows**
4. Congratulations, now you have told Radarr where to store all the movies.

### 3. Downloading Clients

Now we will connect the downloading clients qBittorent and nzbget to Radarr for it to use.

1. Go to Settings &gt; Downloading Clients &gt; + add
2. Select qBittorent and fill in the credentials of your qBittorent downloading client
3. Once done, add another client but this time choose for nzbget.
4. Also fill in here the credentials of your nzbget client with the category "tv"
5. Awesome you are all set !

### 4. Indexers

The final thing we need to setup for our Radarr instance are indexers. However, we will use Prowlarr for this as a centralised indexer for all ARR apps. The only thing we need for Prowlarr to  
connect to Radarr is it's API key.

1. Go to Settings &gt; General
2. Copy paste the API key

# 10. Prowlarr

So Prowlarr is an indexer manager and proxy that integrates with various PVR (Personal Video Recorder) applications, allowing users to manage both Torrent Trackers and Usenet Indexers seamlessly. It works with applications like Radarr, Sonarr, and Lidarr to automate the process of finding and downloading media content. In other words it basically tells all the other ARR applications about the indexers that are available to use to find media content.

### Prowlarr Apps

1. Go to Radarr and obtain its API key at Settings &gt; General &gt; API key
2. Then open up Prowlarr at VMIP:**9696**
3. Go to Settings &gt; Apps &gt; + Icon
4. Then make sure you fill in the subnet IP you created for the servarrnetwork. For instance if your servarrnetwork is 172.44.0.1/24 then your subnet IP will be 172.44.0.1

### Prowlar Indexers

Setting up the nzbgeek indexer in Prowlarr

# 11. Profillar

The next ARR app we will install is profillar. This one, is just really important since it allow you to filter what type and size of content you want all don automatically. If you don't have that much storage space you would not want to download 4K content all the time for instance. On top of that it is hard to see the difference between 4K and 1080p anwyays, even 720p does well on smaller screens. Personally I download everything in 1080p or 720p if I don't care about it to much. The 4K is really not visible on my TV anyways. It gives you just great control over your quality and storage space you have access to.

1. Go to VMIP:**6868**
2. Create an account
3. The first thing we will do just as with Prowlarr is connect it to Radarr and Sonarr.
4. Grab your API keys from both apps again
5. Go to Settings &gt; External Apps &gt; Add Radar and then add Sonarr. The IP address for both Sonarr and Radarr is your VMIP

### Quality Profiles

1. After this we need to add a quality profile repository to our profillar app. There are many different repositories but the one that seems used most often is the following  
    [https://github.com/Dictionarry-Hub/database](https://github.com/Dictionarry-Hub/database "https://github.com/Dictionarry-Hub/database")
2. Then go to

### Media Management

1. Go back to Radarr and Sonarr
2. Go to General &gt; Media Management &gt; Click on Advanced in the left top corner
3. Then scroll down to Propers and Repacks and select "DO NOT PREFER"

# 12. Seerr



# 13. Bazaarr



# Jellyfin Clients

<!--
⚠️ WARNING: DO NOT EDIT THIS FILE ⚠️

This Markdown file is auto-generated from the `assets/clients/clients.yaml` file. 
Any manual changes made to this file will be overwritten the next time it is generated. 
To make changes, please edit the `assets/clients/clients.yaml` file and regenerate this Markdown file.
-->


## 🌎 Browser-Based

| Name | OSS | Free | Paid | Downloads |
| ---- | --- | ---- | ---- | --------- |
| [ampcast ` ⚒️ ` ` 🎵 `](https://github.com/rekkyrosso/ampcast) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/rekkyrosso/ampcast/total?logo=github&label=GitHub)](https://github.com/rekkyrosso/ampcast/releases) |
| [Aperture ` ⚒️ `](https://github.com/akhilmulpurii/aperture) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/akhilmulpurii/aperture/total?logo=github&label=GitHub)](https://github.com/akhilmulpurii/aperture/releases) |
| [Feishin ` ⚒️ ` ` 🎵 `](https://github.com/jeffvli/feishin) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/jeffvli/feishin/total?logo=github&label=GitHub)](https://github.com/jeffvli/feishin/releases) |
| [Finetic](https://github.com/AyaanZaveri/finetic) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/AyaanZaveri/finetic/total?logo=github&label=GitHub)](https://github.com/AyaanZaveri/finetic/releases) |
| [Fladder](https://github.com/DonutWare/Fladder) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/DonutWare/Fladder/total?logo=github&label=GitHub)](https://github.com/DonutWare/Fladder/releases) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=nl.jknaapen.fladder) [![flathub](https://img.shields.io/flathub/downloads/nl.jknaapen.fladder?logo=Flathub&label=Flathub)](https://flathub.org/apps/nl.jknaapen.fladder) |
| [Jelly Music App ` 🎵 `](https://github.com/Stannnnn/jelly-app) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Stannnnn/jelly-app/total?logo=github&label=GitHub)](https://github.com/Stannnnn/jelly-app/releases) |
| [Jellyfin Vue ` 🔹 ` ` ⚒️ `](https://github.com/jellyfin/jellyfin-vue) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/jellyfin/jellyfin-vue/total?logo=github&label=GitHub)](https://github.com/jellyfin/jellyfin-vue/actions/workflows/release.yml) [![Demo](https://img.shields.io/badge/Web-blue?logo=&label=Demo)](https://jf-vue.pages.dev/) |
| [Jellyfin Web ` 🔹 `](https://github.com/jellyfin/jellyfin-web) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/jellyfin/jellyfin-web/total?logo=github&label=GitHub)](https://github.com/jellyfin/jellyfin-web/releases) |
| [Jellyflix](https://github.com/jellyflix-app/jellyflix) | ✅ | ✅ | ❎ | [![Demo](https://img.shields.io/badge/Web-blue?logo=&label=Demo)](https://jellyflix.kiejon.com/) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6476043683) [![github](https://img.shields.io/github/downloads/jellyflix-app/jellyflix/total?logo=github&label=GitHub)](https://github.com/jellyflix-app/jellyflix/releases) |
| [Moonfin](https://github.com/Moonfin-Client) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Moonfin-Client/Moonfin-Core/total?logo=github&label=Core)](https://github.com/Moonfin-Client/Moonfin-Core/releases) [![github](https://img.shields.io/github/downloads/Moonfin-Client/Roku/total?logo=github&label=Roku)](https://github.com/Moonfin-Client/Roku/releases) [![github](https://img.shields.io/github/downloads/Moonfin-Client/Smart-TV/total?logo=github&label=webOS+and+Tizen)](https://github.com/Moonfin-Client/Smart-TV/releases) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=org.moonfin.androidtv) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6761283970) |
| [Pelagica](https://github.com/KartoffelChipss/pelagica) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/KartoffelChipss/pelagica/total?logo=github&label=GitHub)](https://github.com/KartoffelChipss/pelagica/releases) [![Demo](https://img.shields.io/badge/Web-blue?logo=&label=Demo)](https://pelagica.jan.run) |
| [Preserve ` ⚒️ ` ` 🎵 `](https://gitlab.com/preserve/preserve) | ✅ | ✅ | ❎ | [![GitLab](https://img.shields.io/badge/GitLab-grey?logo=GitLab&label=)](https://gitlab.com/preserve/preserve) [![Demo](https://img.shields.io/badge/Web-blue?logo=&label=Demo)](https://preserveplayer.com/) |
| [Shadfin ` ⚒️ `](https://github.com/Shadfin/app) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Shadfin/app/total?logo=github&label=GitHub)](https://github.com/Shadfin/app/releases) [![Demo](https://img.shields.io/badge/Web-blue?logo=&label=Demo)](https://main.shadfin-standalone.pages.dev) |
| [sonixd ` ⚒️ ` ` 🎵 `](https://github.com/jeffvli/sonixd) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/jeffvli/sonixd/total?logo=github&label=GitHub)](https://github.com/jeffvli/sonixd/releases) |


## 💻 Desktop

### Windows

| Name | OSS | Free | Paid | Downloads |
| ---- | --- | ---- | ---- | --------- |
| [ampcast ` ⚒️ ` ` 🎵 `](https://github.com/rekkyrosso/ampcast) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/rekkyrosso/ampcast/total?logo=github&label=GitHub)](https://github.com/rekkyrosso/ampcast/releases) |
| [Blink ` ⚒️ `](https://github.com/prayag17/Blink) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/prayag17/Blink/total?logo=github&label=GitHub)](https://github.com/prayag17/Blink/releases) |
| [Bloodin ` ⚒️ `](https://github.com/pathetic/bloodin) | ✅ | ✅ | ❎ |  |
| [Feishin ` ⚒️ ` ` 🎵 `](https://github.com/jeffvli/feishin) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/jeffvli/feishin/total?logo=github&label=GitHub)](https://github.com/jeffvli/feishin/releases) |
| [Fladder](https://github.com/DonutWare/Fladder) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/DonutWare/Fladder/total?logo=github&label=GitHub)](https://github.com/DonutWare/Fladder/releases) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=nl.jknaapen.fladder) [![flathub](https://img.shields.io/flathub/downloads/nl.jknaapen.fladder?logo=Flathub&label=Flathub)](https://flathub.org/apps/nl.jknaapen.fladder) |
| [FluentFin ` ⚒️ `](https://github.com/insomniachi/FluentFin) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/insomniachi/FluentFin/total?logo=github&label=GitHub)](https://github.com/insomniachi/FluentFin/releases) |
| [Foxy ` 🎵 `](https://github.com/Devioxic/Foxy-Desktop) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Devioxic/Foxy-Desktop/total?logo=github&label=GitHub)](https://github.com/Devioxic/Foxy-Desktop/releases) |
| [Hills](https://play.google.com/store/apps/details?id=com.mountains.hills) | ❌ | ✅ | ☑️ | [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=com.mountains.hills) [![Microsoft Store](https://img.shields.io/badge/-grey?logo=&label=Microsoft+Store)](https://apps.microsoft.com/detail/9NXNZFRLLWZX) |
| [iPlay](https://github.com/saltpi/iPlay) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/saltpi/iPlay/total?logo=github&label=GitHub)](https://github.com/saltpi/iPlay/releases) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6480576133) [![Amazon](https://img.shields.io/badge/Amazon-grey?logo=Amazon&label=)](https://www.amazon.com/gp/product/B0DB2KL58G) [![Microsoft Store](https://img.shields.io/badge/-grey?logo=&label=Microsoft+Store)](https://apps.microsoft.com/detail/9NBZ2BXD4WFZ) |
| [Jelly Music App ` 🎵 `](https://github.com/Stannnnn/jelly-app) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Stannnnn/jelly-app/total?logo=github&label=GitHub)](https://github.com/Stannnnn/jelly-app/releases) |
| [Jellyamp ` 🎵 `](https://github.com/m0ngr31/jellyamp) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/m0ngr31/jellyamp/total?logo=github&label=GitHub)](https://github.com/m0ngr31/jellyamp/releases) |
| [Jellyfin Media Player ` 🔹 `](https://github.com/jellyfin/jellyfin-media-player) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/jellyfin/jellyfin-media-player/total?logo=github&label=GitHub)](https://github.com/jellyfin/jellyfin-media-player/releases) [![flathub](https://img.shields.io/flathub/downloads/com.github.iwalton3.jellyfin-media-player?logo=Flathub&label=Flathub)](https://flathub.org/apps/com.github.iwalton3.jellyfin-media-player) |
| [Jellyfin MPV Shim ` 🔹 `](https://github.com/jellyfin/jellyfin-mpv-shim) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/jellyfin/jellyfin-mpv-shim/total?logo=github&label=GitHub)](https://github.com/jellyfin/jellyfin-mpv-shim/releases) [![flathub](https://img.shields.io/flathub/downloads/com.github.iwalton3.jellyfin-mpv-shim?logo=Flathub&label=Flathub)](https://flathub.org/apps/com.github.iwalton3.jellyfin-mpv-shim) |
| [Jellyflix](https://github.com/jellyflix-app/jellyflix) | ✅ | ✅ | ❎ | [![Demo](https://img.shields.io/badge/Web-blue?logo=&label=Demo)](https://jellyflix.kiejon.com/) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6476043683) [![github](https://img.shields.io/github/downloads/jellyflix-app/jellyflix/total?logo=github&label=GitHub)](https://github.com/jellyflix-app/jellyflix/releases) |
| [Moonfin](https://github.com/Moonfin-Client) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Moonfin-Client/Moonfin-Core/total?logo=github&label=Core)](https://github.com/Moonfin-Client/Moonfin-Core/releases) [![github](https://img.shields.io/github/downloads/Moonfin-Client/Roku/total?logo=github&label=Roku)](https://github.com/Moonfin-Client/Roku/releases) [![github](https://img.shields.io/github/downloads/Moonfin-Client/Smart-TV/total?logo=github&label=webOS+and+Tizen)](https://github.com/Moonfin-Client/Smart-TV/releases) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=org.moonfin.androidtv) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6761283970) |
| [Playtorrio](https://github.com/ayman708-UX/PlayTorrio) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/ayman708-UX/PlayTorrio/total?logo=github&label=GitHub)](https://github.com/ayman708-UX/PlayTorrio/releases) |
| [Preserve ` ⚒️ ` ` 🎵 `](https://gitlab.com/preserve/preserve) | ✅ | ✅ | ❎ | [![GitLab](https://img.shields.io/badge/GitLab-grey?logo=GitLab&label=)](https://gitlab.com/preserve/preserve) [![Demo](https://img.shields.io/badge/Web-blue?logo=&label=Demo)](https://preserveplayer.com/) |
| [Rodel Player](https://apps.microsoft.com/detail/9nb0h051m4v4) | ❌ | ✅ | ❎ | [![Microsoft Store](https://img.shields.io/badge/-grey?logo=&label=Microsoft+Store)](https://apps.microsoft.com/detail/9nb0h051m4v4) |
| [Sonixd ` ⚒️ ` ` 🎵 `](https://github.com/jeffvli/sonixd) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/jeffvli/sonixd/total?logo=github&label=GitHub)](https://github.com/jeffvli/sonixd/releases) |
| [Supersonic ` ⚒️ ` ` 🎵 `](https://github.com/dweymouth/supersonic) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/dweymouth/supersonic/total?logo=github&label=GitHub)](https://github.com/dweymouth/supersonic/releases) [![flathub](https://img.shields.io/flathub/downloads/io.github.dweymouth.supersonic?logo=Flathub&label=Flathub)](https://flathub.org/apps/io.github.dweymouth.supersonic) |
| [Switchfin ` ⚒️ `](https://github.com/dragonflylee/switchfin) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/dragonflylee/switchfin/total?logo=github&label=GitHub)](https://github.com/dragonflylee/switchfin/releases) |
| [Tauon Music Box ` 🎵 `](https://github.com/Taiko2k/TauonMusicBox) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Taiko2k/TauonMusicBox/total?logo=github&label=GitHub)](https://github.com/Taiko2k/TauonMusicBox/releases) [![flathub](https://img.shields.io/flathub/downloads/com.github.taiko2k.tauonmb?logo=Flathub&label=Flathub)](https://flathub.org/apps/com.github.taiko2k.tauonmb) |
| [tsukimi ` ⚒️ `](https://github.com/tsukinaha/tsukimi) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/tsukinaha/tsukimi/total?logo=github&label=GitHub)](https://github.com/tsukinaha/tsukimi/releases) |


### macOS

| Name | OSS | Free | Paid | Downloads |
| ---- | --- | ---- | ---- | --------- |
| [ampcast ` ⚒️ ` ` 🎵 `](https://github.com/rekkyrosso/ampcast) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/rekkyrosso/ampcast/total?logo=github&label=GitHub)](https://github.com/rekkyrosso/ampcast/releases) |
| [Blink ` ⚒️ `](https://github.com/prayag17/Blink) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/prayag17/Blink/total?logo=github&label=GitHub)](https://github.com/prayag17/Blink/releases) |
| [Bloodin ` ⚒️ `](https://github.com/pathetic/bloodin) | ✅ | ✅ | ❎ |  |
| [Coppelia ` ⚒️ ` ` 🎵 `](https://github.com/j6k4m8/coppelia) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/j6k4m8/coppelia/total?logo=github&label=GitHub)](https://github.com/j6k4m8/coppelia/releases) |
| [Dee Jellie ` 🎵 `](https://www.deejellie.com) | ❌ | ❌ | ☑️ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6755585736) |
| [Discrete ` 🎵 `](https://discrete.app/) | ❌ | ✅ | ☑️ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6746067740) |
| [Feishin ` ⚒️ ` ` 🎵 `](https://github.com/jeffvli/feishin) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/jeffvli/feishin/total?logo=github&label=GitHub)](https://github.com/jeffvli/feishin/releases) |
| [Finer ` 🎵 `](https://monk-studio.com/finer) | ❌ | ✅ | ❎ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6738301953) |
| [Fladder](https://github.com/DonutWare/Fladder) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/DonutWare/Fladder/total?logo=github&label=GitHub)](https://github.com/DonutWare/Fladder/releases) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=nl.jknaapen.fladder) [![flathub](https://img.shields.io/flathub/downloads/nl.jknaapen.fladder?logo=Flathub&label=Flathub)](https://flathub.org/apps/nl.jknaapen.fladder) |
| [Foxy ` 🎵 `](https://github.com/Devioxic/Foxy-Desktop) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Devioxic/Foxy-Desktop/total?logo=github&label=GitHub)](https://github.com/Devioxic/Foxy-Desktop/releases) |
| [HamHub](https://www.hamhub.app/) | ❌ | ✅ | ❎ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6458691598) |
| [Infuse](https://firecore.com/infuse) | ❌ | ✅ | ☑️ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id1136220934) |
| [iPlay](https://github.com/saltpi/iPlay) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/saltpi/iPlay/total?logo=github&label=GitHub)](https://github.com/saltpi/iPlay/releases) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6480576133) [![Amazon](https://img.shields.io/badge/Amazon-grey?logo=Amazon&label=)](https://www.amazon.com/gp/product/B0DB2KL58G) [![Microsoft Store](https://img.shields.io/badge/-grey?logo=&label=Microsoft+Store)](https://apps.microsoft.com/detail/9NBZ2BXD4WFZ) |
| [Jelly Music App ` 🎵 `](https://github.com/Stannnnn/jelly-app) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Stannnnn/jelly-app/total?logo=github&label=GitHub)](https://github.com/Stannnnn/jelly-app/releases) |
| [Jellyfin Media Player ` 🔹 `](https://github.com/jellyfin/jellyfin-media-player) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/jellyfin/jellyfin-media-player/total?logo=github&label=GitHub)](https://github.com/jellyfin/jellyfin-media-player/releases) [![flathub](https://img.shields.io/flathub/downloads/com.github.iwalton3.jellyfin-media-player?logo=Flathub&label=Flathub)](https://flathub.org/apps/com.github.iwalton3.jellyfin-media-player) |
| [Jellyfin MPV Shim ` 🔹 `](https://github.com/jellyfin/jellyfin-mpv-shim) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/jellyfin/jellyfin-mpv-shim/total?logo=github&label=GitHub)](https://github.com/jellyfin/jellyfin-mpv-shim/releases) [![flathub](https://img.shields.io/flathub/downloads/com.github.iwalton3.jellyfin-mpv-shim?logo=Flathub&label=Flathub)](https://flathub.org/apps/com.github.iwalton3.jellyfin-mpv-shim) |
| [Jellyflix](https://github.com/jellyflix-app/jellyflix) | ✅ | ✅ | ❎ | [![Demo](https://img.shields.io/badge/Web-blue?logo=&label=Demo)](https://jellyflix.kiejon.com/) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6476043683) [![github](https://img.shields.io/github/downloads/jellyflix-app/jellyflix/total?logo=github&label=GitHub)](https://github.com/jellyflix-app/jellyflix/releases) |
| [Moonfin](https://github.com/Moonfin-Client) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Moonfin-Client/Moonfin-Core/total?logo=github&label=Core)](https://github.com/Moonfin-Client/Moonfin-Core/releases) [![github](https://img.shields.io/github/downloads/Moonfin-Client/Roku/total?logo=github&label=Roku)](https://github.com/Moonfin-Client/Roku/releases) [![github](https://img.shields.io/github/downloads/Moonfin-Client/Smart-TV/total?logo=github&label=webOS+and+Tizen)](https://github.com/Moonfin-Client/Smart-TV/releases) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=org.moonfin.androidtv) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6761283970) |
| [Phyn](https://phyn.app) | ❌ | ✅ | ☑️ | [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=com.appsynergyts.phyn) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6457674815) |
| [Playtorrio](https://github.com/ayman708-UX/PlayTorrio) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/ayman708-UX/PlayTorrio/total?logo=github&label=GitHub)](https://github.com/ayman708-UX/PlayTorrio/releases) |
| [SenPlayer](https://apps.apple.com/app/id6443975850) | ❌ | ✅ | ☑️ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6443975850) |
| [Sonixd ` ⚒️ ` ` 🎵 `](https://github.com/jeffvli/sonixd) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/jeffvli/sonixd/total?logo=github&label=GitHub)](https://github.com/jeffvli/sonixd/releases) |
| [Supersonic ` ⚒️ ` ` 🎵 `](https://github.com/dweymouth/supersonic) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/dweymouth/supersonic/total?logo=github&label=GitHub)](https://github.com/dweymouth/supersonic/releases) [![flathub](https://img.shields.io/flathub/downloads/io.github.dweymouth.supersonic?logo=Flathub&label=Flathub)](https://flathub.org/apps/io.github.dweymouth.supersonic) |
| [Switchfin ` ⚒️ `](https://github.com/dragonflylee/switchfin) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/dragonflylee/switchfin/total?logo=github&label=GitHub)](https://github.com/dragonflylee/switchfin/releases) |
| [VidHub](https://okaapps.com/product/1659622164) | ❌ | ✅ | ☑️ | [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=com.oumi.utility.media.hub) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id1659622164) |


### Linux

| Name | OSS | Free | Paid | Downloads |
| ---- | --- | ---- | ---- | --------- |
| [ampcast ` ⚒️ ` ` 🎵 `](https://github.com/rekkyrosso/ampcast) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/rekkyrosso/ampcast/total?logo=github&label=GitHub)](https://github.com/rekkyrosso/ampcast/releases) |
| [Blink ` ⚒️ `](https://github.com/prayag17/Blink) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/prayag17/Blink/total?logo=github&label=GitHub)](https://github.com/prayag17/Blink/releases) |
| [Bloodin ` ⚒️ `](https://github.com/pathetic/bloodin) | ✅ | ✅ | ❎ |  |
| [Coppelia ` ⚒️ ` ` 🎵 `](https://github.com/j6k4m8/coppelia) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/j6k4m8/coppelia/total?logo=github&label=GitHub)](https://github.com/j6k4m8/coppelia/releases) |
| [Delfin ` ⚒️ `](https://codeberg.org/avery42/delfin) | ✅ | ✅ | ❎ | [![flathub](https://img.shields.io/flathub/downloads/cafe.avery.Delfin?logo=Flathub&label=Flathub)](https://flathub.org/apps/cafe.avery.Delfin) |
| [Feishin ` ⚒️ ` ` 🎵 `](https://github.com/jeffvli/feishin) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/jeffvli/feishin/total?logo=github&label=GitHub)](https://github.com/jeffvli/feishin/releases) |
| [Fladder](https://github.com/DonutWare/Fladder) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/DonutWare/Fladder/total?logo=github&label=GitHub)](https://github.com/DonutWare/Fladder/releases) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=nl.jknaapen.fladder) [![flathub](https://img.shields.io/flathub/downloads/nl.jknaapen.fladder?logo=Flathub&label=Flathub)](https://flathub.org/apps/nl.jknaapen.fladder) |
| [Foxy ` 🎵 `](https://github.com/Devioxic/Foxy-Desktop) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Devioxic/Foxy-Desktop/total?logo=github&label=GitHub)](https://github.com/Devioxic/Foxy-Desktop/releases) |
| [Gelly ` ⚒️ ` ` 🎵 `](https://github.com/Fingel/gelly) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Fingel/gelly/total?logo=github&label=GitHub)](https://github.com/Fingel/gelly/releases) [![flathub](https://img.shields.io/flathub/downloads/io.m51.Gelly?logo=Flathub&label=Flathub)](https://flathub.org/apps/io.m51.Gelly) |
| [Jelly Music App ` 🎵 `](https://github.com/Stannnnn/jelly-app) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Stannnnn/jelly-app/total?logo=github&label=GitHub)](https://github.com/Stannnnn/jelly-app/releases) |
| [Jellyamp ` 🎵 `](https://github.com/m0ngr31/jellyamp) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/m0ngr31/jellyamp/total?logo=github&label=GitHub)](https://github.com/m0ngr31/jellyamp/releases) |
| [Jellyfin Media Player ` 🔹 `](https://github.com/jellyfin/jellyfin-media-player) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/jellyfin/jellyfin-media-player/total?logo=github&label=GitHub)](https://github.com/jellyfin/jellyfin-media-player/releases) [![flathub](https://img.shields.io/flathub/downloads/com.github.iwalton3.jellyfin-media-player?logo=Flathub&label=Flathub)](https://flathub.org/apps/com.github.iwalton3.jellyfin-media-player) |
| [Jellyfin MPV Shim ` 🔹 `](https://github.com/jellyfin/jellyfin-mpv-shim) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/jellyfin/jellyfin-mpv-shim/total?logo=github&label=GitHub)](https://github.com/jellyfin/jellyfin-mpv-shim/releases) [![flathub](https://img.shields.io/flathub/downloads/com.github.iwalton3.jellyfin-mpv-shim?logo=Flathub&label=Flathub)](https://flathub.org/apps/com.github.iwalton3.jellyfin-mpv-shim) |
| [Jellyflix](https://github.com/jellyflix-app/jellyflix) | ✅ | ✅ | ❎ | [![Demo](https://img.shields.io/badge/Web-blue?logo=&label=Demo)](https://jellyflix.kiejon.com/) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6476043683) [![github](https://img.shields.io/github/downloads/jellyflix-app/jellyflix/total?logo=github&label=GitHub)](https://github.com/jellyflix-app/jellyflix/releases) |
| [Moonfin](https://github.com/Moonfin-Client) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Moonfin-Client/Moonfin-Core/total?logo=github&label=Core)](https://github.com/Moonfin-Client/Moonfin-Core/releases) [![github](https://img.shields.io/github/downloads/Moonfin-Client/Roku/total?logo=github&label=Roku)](https://github.com/Moonfin-Client/Roku/releases) [![github](https://img.shields.io/github/downloads/Moonfin-Client/Smart-TV/total?logo=github&label=webOS+and+Tizen)](https://github.com/Moonfin-Client/Smart-TV/releases) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=org.moonfin.androidtv) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6761283970) |
| [Playtorrio](https://github.com/ayman708-UX/PlayTorrio) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/ayman708-UX/PlayTorrio/total?logo=github&label=GitHub)](https://github.com/ayman708-UX/PlayTorrio/releases) |
| [Preserve ` ⚒️ ` ` 🎵 `](https://gitlab.com/preserve/preserve) | ✅ | ✅ | ❎ | [![GitLab](https://img.shields.io/badge/GitLab-grey?logo=GitLab&label=)](https://gitlab.com/preserve/preserve) [![Demo](https://img.shields.io/badge/Web-blue?logo=&label=Demo)](https://preserveplayer.com/) |
| [Sonixd ` ⚒️ ` ` 🎵 `](https://github.com/jeffvli/sonixd) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/jeffvli/sonixd/total?logo=github&label=GitHub)](https://github.com/jeffvli/sonixd/releases) |
| [Supersonic ` ⚒️ ` ` 🎵 `](https://github.com/dweymouth/supersonic) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/dweymouth/supersonic/total?logo=github&label=GitHub)](https://github.com/dweymouth/supersonic/releases) [![flathub](https://img.shields.io/flathub/downloads/io.github.dweymouth.supersonic?logo=Flathub&label=Flathub)](https://flathub.org/apps/io.github.dweymouth.supersonic) |
| [Switchfin ` ⚒️ `](https://github.com/dragonflylee/switchfin) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/dragonflylee/switchfin/total?logo=github&label=GitHub)](https://github.com/dragonflylee/switchfin/releases) |
| [Tauon Music Box ` 🎵 `](https://github.com/Taiko2k/TauonMusicBox) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Taiko2k/TauonMusicBox/total?logo=github&label=GitHub)](https://github.com/Taiko2k/TauonMusicBox/releases) [![flathub](https://img.shields.io/flathub/downloads/com.github.taiko2k.tauonmb?logo=Flathub&label=Flathub)](https://flathub.org/apps/com.github.taiko2k.tauonmb) |
| [tsukimi ` ⚒️ `](https://github.com/tsukinaha/tsukimi) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/tsukinaha/tsukimi/total?logo=github&label=GitHub)](https://github.com/tsukinaha/tsukimi/releases) |


## 📱 Mobile

### iOS

| Name | OSS | Free | Paid | Downloads |
| ---- | --- | ---- | ---- | --------- |
| [Coppelia ` ⚒️ ` ` 🎵 `](https://github.com/j6k4m8/coppelia) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/j6k4m8/coppelia/total?logo=github&label=GitHub)](https://github.com/j6k4m8/coppelia/releases) |
| [Dee Jellie ` 🎵 `](https://www.deejellie.com) | ❌ | ❌ | ☑️ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6755585736) |
| [Discrete ` 🎵 `](https://discrete.app/) | ❌ | ✅ | ☑️ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6746067740) |
| [Filebar](https://fileball.app/) | ❌ | ✅ | ☑️ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id1558391784) |
| [Finamp ` 🎵 `](https://github.com/jmshrv/finamp) | ✅ | ✅ | ❎ | [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=com.unicornsonlsd.finamp) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id1574922594) |
| [Finer ` 🎵 `](https://monk-studio.com/finer) | ❌ | ✅ | ❎ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6738301953) |
| [Fintunes ` 🎵 `](https://github.com/leinelissen/jellyfin-audio-player) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/leinelissen/jellyfin-audio-player/total?logo=github&label=GitHub)](https://github.com/leinelissen/jellyfin-audio-player/releases) [![F-Droid](https://img.shields.io/badge/F-Droid-grey?logo=F-Droid&label=)](https://f-droid.org/en/packages/nl.moeilijkedingen.jellyfinaudioplayer) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=nl.moeilijkedingen.jellyfinaudioplayer) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id1527732194) |
| [Fladder](https://github.com/DonutWare/Fladder) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/DonutWare/Fladder/total?logo=github&label=GitHub)](https://github.com/DonutWare/Fladder/releases) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=nl.jknaapen.fladder) [![flathub](https://img.shields.io/flathub/downloads/nl.jknaapen.fladder?logo=Flathub&label=Flathub)](https://flathub.org/apps/nl.jknaapen.fladder) |
| [HamHub](https://www.hamhub.app/) | ❌ | ✅ | ❎ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6458691598) |
| [Infuse](https://firecore.com/infuse) | ❌ | ✅ | ☑️ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id1136220934) |
| [iPlay](https://github.com/saltpi/iPlay) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/saltpi/iPlay/total?logo=github&label=GitHub)](https://github.com/saltpi/iPlay/releases) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6480576133) [![Amazon](https://img.shields.io/badge/Amazon-grey?logo=Amazon&label=)](https://www.amazon.com/gp/product/B0DB2KL58G) [![Microsoft Store](https://img.shields.io/badge/-grey?logo=&label=Microsoft+Store)](https://apps.microsoft.com/detail/9NBZ2BXD4WFZ) |
| [Jellify ` 🎵 `](https://github.com/Jellify-Music/App) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Jellify-Music/App/total?logo=github&label=GitHub)](https://github.com/Jellify-Music/App/releases) [![TestFlight](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=TestFlight)](https://testflight.apple.com/join/etVSc7ZQ) |
| [JellyBook ` 📖 `](https://github.com/JellyBookOrg/JellyBook) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/JellyBookOrg/JellyBook/total?logo=github&label=GitHub)](https://github.com/JellyBookOrg/JellyBook/releases) [![Izzysoft](https://img.shields.io/badge/-grey?logo=&label=Izzysoft)](https://apt.izzysoft.de/fdroid/index/apk/com.KaraWilson.JellyBook/) [![TestFlight](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=TestFlight)](https://testflight.apple.com/join/lEXKY4Dl) |
| [Jellyfin Mobile for iOS ` 🔹 `](https://github.com/jellyfin/jellyfin-expo) | ✅ | ✅ | ❎ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id1480192618) |
| [Jellyflix](https://github.com/jellyflix-app/jellyflix) | ✅ | ✅ | ❎ | [![Demo](https://img.shields.io/badge/Web-blue?logo=&label=Demo)](https://jellyflix.kiejon.com/) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6476043683) [![github](https://img.shields.io/github/downloads/jellyflix-app/jellyflix/total?logo=github&label=GitHub)](https://github.com/jellyflix-app/jellyflix/releases) |
| [JellyTV](https://jellytv.app/en) | ❌ | ❌ | ☑️ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6752357290) |
| [Manet ` 🎵 `](https://tilo.dev/manet/) | ❌ | ✅ | ❎ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6470928235) |
| [Moonfin](https://github.com/Moonfin-Client) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Moonfin-Client/Moonfin-Core/total?logo=github&label=Core)](https://github.com/Moonfin-Client/Moonfin-Core/releases) [![github](https://img.shields.io/github/downloads/Moonfin-Client/Roku/total?logo=github&label=Roku)](https://github.com/Moonfin-Client/Roku/releases) [![github](https://img.shields.io/github/downloads/Moonfin-Client/Smart-TV/total?logo=github&label=webOS+and+Tizen)](https://github.com/Moonfin-Client/Smart-TV/releases) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=org.moonfin.androidtv) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6761283970) |
| [Phyn](https://phyn.app) | ❌ | ✅ | ☑️ | [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=com.appsynergyts.phyn) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6457674815) |
| [Plappa ` 🎵 `](https://github.com/LeoKlaus/plappa) | ✅ | ✅ | ❎ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6475201956) |
| [SenPlayer](https://apps.apple.com/app/id6443975850) | ❌ | ✅ | ☑️ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6443975850) |
| [Streamyfin](https://streamyfin.app) | ✅ | ✅ | ❎ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6593660679) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=com.fredrikburmester.streamyfin) [![github](https://img.shields.io/github/downloads/fredrikburmester/streamyfin/total?logo=github&label=GitHub)](https://github.com/fredrikburmester/streamyfin/releases) |
| [Sunkfin](https://github.com/jackcrane/sunkfin) | ✅ | ✅ | ❎ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6743207349) |
| [Swiftfin ` 🔹 ` ` ⚒️ `](https://github.com/jellyfin/swiftfin) | ✅ | ✅ | ❎ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id1604098728) |
| [VidHub](https://okaapps.com/product/1659622164) | ❌ | ✅ | ☑️ | [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=com.oumi.utility.media.hub) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id1659622164) |
| [yybx](https://yybpro.com) | ❌ | ❌ | ☑️ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id1519723194) |


### Android

| Name | OSS | Free | Paid | Downloads |
| ---- | --- | ---- | ---- | --------- |
| [AFinity ` ⚒️ `](https://github.com/MakD/AFinity) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/MakD/AFinity/total?logo=github&label=GitHub)](https://github.com/MakD/AFinity/releases) |
| [AfuseKt](https://github.com/AttemptD/AfuseKt-release) | ❌ | ✅ | ☑️ | [![github](https://img.shields.io/github/downloads/AttemptD/AfuseKt-release/total?logo=github&label=GitHub)](https://github.com/AttemptD/AfuseKt-release/releases) |
| [Coppelia ` ⚒️ ` ` 🎵 `](https://github.com/j6k4m8/coppelia) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/j6k4m8/coppelia/total?logo=github&label=GitHub)](https://github.com/j6k4m8/coppelia/releases) |
| [Finamp ` 🎵 `](https://github.com/jmshrv/finamp) | ✅ | ✅ | ❎ | [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=com.unicornsonlsd.finamp) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id1574922594) |
| [Findroid ` ⚒️ `](https://github.com/jarnedemeulemeester/findroid) | ✅ | ✅ | ❎ | [![Izzysoft](https://img.shields.io/badge/-grey?logo=&label=Izzysoft)](https://apt.izzysoft.de/fdroid/index/apk/dev.jdtech.jellyfin) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=dev.jdtech.jellyfin) [![F-Droid](https://img.shields.io/badge/F-Droid-grey?logo=F-Droid&label=)](https://f-droid.org/en/packages/dev.jdtech.jellyfin/) |
| [Fintunes ` 🎵 `](https://github.com/leinelissen/jellyfin-audio-player) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/leinelissen/jellyfin-audio-player/total?logo=github&label=GitHub)](https://github.com/leinelissen/jellyfin-audio-player/releases) [![F-Droid](https://img.shields.io/badge/F-Droid-grey?logo=F-Droid&label=)](https://f-droid.org/en/packages/nl.moeilijkedingen.jellyfinaudioplayer) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=nl.moeilijkedingen.jellyfinaudioplayer) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id1527732194) |
| [Fladder](https://github.com/DonutWare/Fladder) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/DonutWare/Fladder/total?logo=github&label=GitHub)](https://github.com/DonutWare/Fladder/releases) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=nl.jknaapen.fladder) [![flathub](https://img.shields.io/flathub/downloads/nl.jknaapen.fladder?logo=Flathub&label=Flathub)](https://flathub.org/apps/nl.jknaapen.fladder) |
| [Gelli ` 🎵 `](https://github.com/dkanada/gelli) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/dkanada/gelli/total?logo=github&label=GitHub)](https://github.com/dkanada/gelli/releases) [![F-Droid](https://img.shields.io/badge/F-Droid-grey?logo=F-Droid&label=)](https://f-droid.org/packages/com.dkanada.gramophone) |
| [Ghosten-Player](https://github.com/GhostenEditor/Ghosten-Player) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/GhostenEditor/Ghosten-Player/total?logo=github&label=GitHub)](https://github.com/GhostenEditor/Ghosten-Player/releases) |
| [Hills](https://play.google.com/store/apps/details?id=com.mountains.hills) | ❌ | ✅ | ☑️ | [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=com.mountains.hills) [![Microsoft Store](https://img.shields.io/badge/-grey?logo=&label=Microsoft+Store)](https://apps.microsoft.com/detail/9NXNZFRLLWZX) |
| [Jellify ` 🎵 `](https://github.com/Jellify-Music/App) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Jellify-Music/App/total?logo=github&label=GitHub)](https://github.com/Jellify-Music/App/releases) [![TestFlight](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=TestFlight)](https://testflight.apple.com/join/etVSc7ZQ) |
| [JellyBook ` 📖 `](https://github.com/JellyBookOrg/JellyBook) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/JellyBookOrg/JellyBook/total?logo=github&label=GitHub)](https://github.com/JellyBookOrg/JellyBook/releases) [![Izzysoft](https://img.shields.io/badge/-grey?logo=&label=Izzysoft)](https://apt.izzysoft.de/fdroid/index/apk/com.KaraWilson.JellyBook/) [![TestFlight](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=TestFlight)](https://testflight.apple.com/join/lEXKY4Dl) |
| [JellyCine](https://github.com/sureshfizzy/JellyCine) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/sureshfizzy/JellyCine/total?logo=github&label=GitHub)](https://github.com/sureshfizzy/JellyCine/releases) |
| [Jellyfin for Android ` 🔹 `](https://github.com/jellyfin/jellyfin-android) | ✅ | ✅ | ❎ | [![F-Droid](https://img.shields.io/badge/F-Droid-grey?logo=F-Droid&label=)](https://f-droid.org/en/packages/org.jellyfin.mobile/) [![Amazon](https://img.shields.io/badge/Amazon-grey?logo=Amazon&label=)](https://www.amazon.com/gp/aw/d/B081RFTTQ9) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=org.jellyfin.mobile) |
| [Jellyflix](https://github.com/jellyflix-app/jellyflix) | ✅ | ✅ | ❎ | [![Demo](https://img.shields.io/badge/Web-blue?logo=&label=Demo)](https://jellyflix.kiejon.com/) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6476043683) [![github](https://img.shields.io/github/downloads/jellyflix-app/jellyflix/total?logo=github&label=GitHub)](https://github.com/jellyflix-app/jellyflix/releases) |
| [Moonfin](https://github.com/Moonfin-Client) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Moonfin-Client/Moonfin-Core/total?logo=github&label=Core)](https://github.com/Moonfin-Client/Moonfin-Core/releases) [![github](https://img.shields.io/github/downloads/Moonfin-Client/Roku/total?logo=github&label=Roku)](https://github.com/Moonfin-Client/Roku/releases) [![github](https://img.shields.io/github/downloads/Moonfin-Client/Smart-TV/total?logo=github&label=webOS+and+Tizen)](https://github.com/Moonfin-Client/Smart-TV/releases) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=org.moonfin.androidtv) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6761283970) |
| [Phyn](https://phyn.app) | ❌ | ✅ | ☑️ | [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=com.appsynergyts.phyn) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6457674815) |
| [Playtorrio](https://github.com/ayman708-UX/PlayTorrio) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/ayman708-UX/PlayTorrio/total?logo=github&label=GitHub)](https://github.com/ayman708-UX/PlayTorrio/releases) |
| [Reefin](https://reefin.dev/) | ❌ | ❌ | ❎ | [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=com.shady.reefin) [![github](https://img.shields.io/github/downloads/SKULSHADY/reefin/total?logo=github&label=GitHub)](https://github.com/SKULSHADY/reefin/releases) |
| [Streamyfin](https://streamyfin.app) | ✅ | ✅ | ❎ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6593660679) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=com.fredrikburmester.streamyfin) [![github](https://img.shields.io/github/downloads/fredrikburmester/streamyfin/total?logo=github&label=GitHub)](https://github.com/fredrikburmester/streamyfin/releases) |
| [Symfonium ` ⚒️ ` ` 🎵 `](https://symfonium.app) | ❌ | ❌ | ☑️ | [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=app.symfonik.music.player) |
| [VidHub](https://okaapps.com/product/1659622164) | ❌ | ✅ | ☑️ | [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=com.oumi.utility.media.hub) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id1659622164) |
| [Void ` ⚒️ `](https://github.com/hritwikjohri/Void-for-jellyfin) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/hritwikjohri/Void-for-jellyfin/total?logo=github&label=GitHub)](https://github.com/hritwikjohri/Void-for-jellyfin/releases) [![github](https://img.shields.io/github/downloads/hritwikjohri/VoidTV-for-jellyfin/total?logo=github&label=GitHub)](https://github.com/hritwikjohri/VoidTV-for-jellyfin/releases) |
| Yamby | ❌ | ✅ | ☑️ | [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=com.hush.yamby) |


### Sailfish OS

| Name | OSS | Free | Paid | Downloads |
| ---- | --- | ---- | ---- | --------- |
| [Sailfin](https://github.com/heartfin/harbour-sailfin) | ✅ | ✅ | ❎ | [![OpenRepos](https://img.shields.io/badge/-grey?logo=&label=OpenRepos)](https://openrepos.net/content/ahappyhuman/sailfin) |


### HarmonyOS

| Name | OSS | Free | Paid | Downloads |
| ---- | --- | ---- | ---- | --------- |
| [FinMusic ` 🎵 `](https://github.com/OHPG/FinMusic) | ✅ | ✅ | ❎ | [![AppGallery](https://img.shields.io/badge/AppGallery-grey?logo=AppGallery&label=)](https://appgallery.huawei.com/app/detail?id=org.ohpg.fin.music) [![github](https://img.shields.io/github/downloads/OHPG/FinMusic/total?logo=github&label=GitHub)](https://github.com/OHPG/FinMusic/releases) |
| [FinVideo](https://github.com/OHPG/FinVideo) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/OHPG/FinVideo/total?logo=github&label=GitHub)](https://github.com/OHPG/FinVideo/releases) [![AppGallery](https://img.shields.io/badge/AppGallery-grey?logo=AppGallery&label=)](https://appgallery.huawei.com/app/detail?id=org.ohpg.fin.video) |


### Nintendo Switch

| Name | OSS | Free | Paid | Downloads |
| ---- | --- | ---- | ---- | --------- |
| [Switchfin ` ⚒️ `](https://github.com/dragonflylee/switchfin) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/dragonflylee/switchfin/total?logo=github&label=GitHub)](https://github.com/dragonflylee/switchfin/releases) |


## 📺 TV

### Apple TV

| Name | OSS | Free | Paid | Downloads |
| ---- | --- | ---- | ---- | --------- |
| [Dee Jellie ` 🎵 `](https://www.deejellie.com) | ❌ | ❌ | ☑️ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6755585736) |
| [Filebar](https://fileball.app/) | ❌ | ✅ | ☑️ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id1558391784) |
| [HamHub](https://www.hamhub.app/) | ❌ | ✅ | ❎ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6458691598) |
| [Infuse](https://firecore.com/infuse) | ❌ | ✅ | ☑️ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id1136220934) |
| JellySee | ❌ | ❌ | ☑️ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6748783768) |
| [Mediora](https://github.com/ghobs91/mediora) | ✅ | ✅ | ❎ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6757345487) |
| [Moonfin](https://github.com/Moonfin-Client) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Moonfin-Client/Moonfin-Core/total?logo=github&label=Core)](https://github.com/Moonfin-Client/Moonfin-Core/releases) [![github](https://img.shields.io/github/downloads/Moonfin-Client/Roku/total?logo=github&label=Roku)](https://github.com/Moonfin-Client/Roku/releases) [![github](https://img.shields.io/github/downloads/Moonfin-Client/Smart-TV/total?logo=github&label=webOS+and+Tizen)](https://github.com/Moonfin-Client/Smart-TV/releases) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=org.moonfin.androidtv) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6761283970) |
| [MrMC](https://github.com/MrMC/mrmc) | ✅ | ✅ | ☑️ | [![Amazon](https://img.shields.io/badge/Amazon-grey?logo=Amazon&label=)](https://www.amazon.com/gp/product/B01ENT3I1Q/ref=mas_pm_mrmc) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id1059536415) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=tv.mrmc.mrmc) |
| [SenPlayer](https://apps.apple.com/app/id6443975850) | ❌ | ✅ | ☑️ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6443975850) |
| [Swiftfin ` 🔹 ` ` ⚒️ `](https://github.com/jellyfin/swiftfin) | ✅ | ✅ | ❎ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id1604098728) |
| [VidHub](https://okaapps.com/product/1659622164) | ❌ | ✅ | ☑️ | [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=com.oumi.utility.media.hub) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id1659622164) |
| [yybx](https://yybpro.com) | ❌ | ❌ | ☑️ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id1519723194) |


### Android TV

| Name | OSS | Free | Paid | Downloads |
| ---- | --- | ---- | ---- | --------- |
| [AfuseKt TV](https://github.com/AttemptD/AfuseKtV-release) | ❌ | ❌ | ☑️ | [![github](https://img.shields.io/github/downloads/AttemptD/AfuseKtV-release/total?logo=github&label=GitHub)](https://github.com/AttemptD/AfuseKtV-release/releases) |
| [DUNE ` ⚒️ `](https://github.com/Sam42a/DUNE) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Sam42a/DUNE/total?logo=github&label=GitHub)](https://github.com/Sam42a/DUNE/releases) |
| [Elefin](https://github.com/flex36ty/elefin) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/flex36ty/elefin/total?logo=github&label=GitHub)](https://github.com/flex36ty/elefin/releases) |
| [Fladder](https://github.com/DonutWare/Fladder) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/DonutWare/Fladder/total?logo=github&label=GitHub)](https://github.com/DonutWare/Fladder/releases) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=nl.jknaapen.fladder) [![flathub](https://img.shields.io/flathub/downloads/nl.jknaapen.fladder?logo=Flathub&label=Flathub)](https://flathub.org/apps/nl.jknaapen.fladder) |
| [Ghosten-Player](https://github.com/GhostenEditor/Ghosten-Player) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/GhostenEditor/Ghosten-Player/total?logo=github&label=GitHub)](https://github.com/GhostenEditor/Ghosten-Player/releases) |
| [Jellyfin for Android TV ` 🔹 `](https://github.com/jellyfin/jellyfin-androidtv) | ✅ | ✅ | ❎ | [![Amazon](https://img.shields.io/badge/Amazon-grey?logo=Amazon&label=)](https://www.amazon.com/gp/aw/d/B07TX7Z725) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=org.jellyfin.androidtv) |
| [Moonfin](https://github.com/Moonfin-Client) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Moonfin-Client/Moonfin-Core/total?logo=github&label=Core)](https://github.com/Moonfin-Client/Moonfin-Core/releases) [![github](https://img.shields.io/github/downloads/Moonfin-Client/Roku/total?logo=github&label=Roku)](https://github.com/Moonfin-Client/Roku/releases) [![github](https://img.shields.io/github/downloads/Moonfin-Client/Smart-TV/total?logo=github&label=webOS+and+Tizen)](https://github.com/Moonfin-Client/Smart-TV/releases) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=org.moonfin.androidtv) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6761283970) |
| [Reefin](https://reefin.dev/) | ❌ | ❌ | ❎ | [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=com.shady.reefin) [![github](https://img.shields.io/github/downloads/SKULSHADY/reefin/total?logo=github&label=GitHub)](https://github.com/SKULSHADY/reefin/releases) |
| [VidHub](https://okaapps.com/product/1659622164) | ❌ | ✅ | ☑️ | [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=com.oumi.utility.media.hub) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id1659622164) |
| [Void ` ⚒️ `](https://github.com/hritwikjohri/Void-for-jellyfin) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/hritwikjohri/Void-for-jellyfin/total?logo=github&label=GitHub)](https://github.com/hritwikjohri/Void-for-jellyfin/releases) [![github](https://img.shields.io/github/downloads/hritwikjohri/VoidTV-for-jellyfin/total?logo=github&label=GitHub)](https://github.com/hritwikjohri/VoidTV-for-jellyfin/releases) |
| [Wholphin](https://github.com/damontecres/Wholphin) | ✅ | ✅ | ❎ | [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=com.github.damontecres.wholphin) [![github](https://img.shields.io/github/downloads/damontecres/Wholphin/total?logo=github&label=GitHub)](https://github.com/damontecres/Wholphin/releases) |
| Yamby | ❌ | ✅ | ☑️ | [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=com.hush.yamby) |


### Kodi

| Name | OSS | Free | Paid | Downloads |
| ---- | --- | ---- | ---- | --------- |
| [JellyCon ` 🔹 `](https://github.com/jellyfin/jellycon) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/jellyfin/jellycon/total?logo=github&label=GitHub)](https://github.com/jellyfin/jellycon/releases) |
| [Jellyfin for Kodi ` 🔹 `](https://github.com/jellyfin/jellyfin-kodi) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/jellyfin/jellyfin-kodi/total?logo=github&label=GitHub)](https://github.com/jellyfin/jellyfin-kodi/releases) |


### Roku

| Name | OSS | Free | Paid | Downloads |
| ---- | --- | ---- | ---- | --------- |
| [Jellyfin for Roku ` 🔹 `](https://github.com/jellyfin/jellyfin-roku) | ✅ | ✅ | ❎ | [![Roku](https://img.shields.io/badge/Roku-grey?logo=Roku&label=)](https://channelstore.roku.com/details/592369/jellyfin) |
| [JellyRock](https://github.com/cewert/jellyrock) | ✅ | ✅ | ❎ | [![Roku](https://img.shields.io/badge/Roku-grey?logo=Roku&label=)](https://channelstore.roku.com/details/232f9e82db11ce628e3fe7e01382a330:a85d6e9e520567806e8dae1c0cabadd5/jellyrock) [![github](https://img.shields.io/github/downloads/cewert/jellyrock/total?logo=github&label=GitHub)](https://github.com/cewert/jellyrock/releases) |
| [Moonfin](https://github.com/Moonfin-Client) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Moonfin-Client/Moonfin-Core/total?logo=github&label=Core)](https://github.com/Moonfin-Client/Moonfin-Core/releases) [![github](https://img.shields.io/github/downloads/Moonfin-Client/Roku/total?logo=github&label=Roku)](https://github.com/Moonfin-Client/Roku/releases) [![github](https://img.shields.io/github/downloads/Moonfin-Client/Smart-TV/total?logo=github&label=webOS+and+Tizen)](https://github.com/Moonfin-Client/Smart-TV/releases) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=org.moonfin.androidtv) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6761283970) |


### Tizen

| Name | OSS | Free | Paid | Downloads |
| ---- | --- | ---- | ---- | --------- |
| [Jellyfin for Tizen ` 🔹 `](https://github.com/jellyfin/jellyfin-tizen) | ✅ | ✅ | ❎ | [Build It Yourself](https://github.com/jellyfin/jellyfin-tizen) |
| [Litefin](https://github.com/MoazSalem/litefin) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/MoazSalem/litefin/total?logo=github&label=GitHub)](https://github.com/MoazSalem/litefin/releases) |
| [Moonfin](https://github.com/Moonfin-Client) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Moonfin-Client/Moonfin-Core/total?logo=github&label=Core)](https://github.com/Moonfin-Client/Moonfin-Core/releases) [![github](https://img.shields.io/github/downloads/Moonfin-Client/Roku/total?logo=github&label=Roku)](https://github.com/Moonfin-Client/Roku/releases) [![github](https://img.shields.io/github/downloads/Moonfin-Client/Smart-TV/total?logo=github&label=webOS+and+Tizen)](https://github.com/Moonfin-Client/Smart-TV/releases) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=org.moonfin.androidtv) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6761283970) |


### webOS

| Name | OSS | Free | Paid | Downloads |
| ---- | --- | ---- | ---- | --------- |
| [Breezyfin ` ⚒️ `](https://github.com/botagas/Breezyfin) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/botagas/Breezyfin/total?logo=github&label=GitHub)](https://github.com/botagas/Breezyfin/releases) |
| [Jellyfin for WebOS ` 🔹 `](https://github.com/jellyfin/jellyfin-webos) | ✅ | ✅ | ❎ | [![LG](https://img.shields.io/badge/LG-grey?logo=LG&label=)](https://us.lgappstv.com/main/tvapp/detail?appId=1030579) |
| [Litefin](https://github.com/MoazSalem/litefin) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/MoazSalem/litefin/total?logo=github&label=GitHub)](https://github.com/MoazSalem/litefin/releases) |
| [Moonfin](https://github.com/Moonfin-Client) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Moonfin-Client/Moonfin-Core/total?logo=github&label=Core)](https://github.com/Moonfin-Client/Moonfin-Core/releases) [![github](https://img.shields.io/github/downloads/Moonfin-Client/Roku/total?logo=github&label=Roku)](https://github.com/Moonfin-Client/Roku/releases) [![github](https://img.shields.io/github/downloads/Moonfin-Client/Smart-TV/total?logo=github&label=webOS+and+Tizen)](https://github.com/Moonfin-Client/Smart-TV/releases) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=org.moonfin.androidtv) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6761283970) |


---

# By Type

## ` 🎵 ` Music Client

| Name | OSS | Free | Paid | Downloads |
| ---- | --- | ---- | ---- | --------- |
| [ampcast ` ⚒️ ` ` 🎵 `](https://github.com/rekkyrosso/ampcast) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/rekkyrosso/ampcast/total?logo=github&label=GitHub)](https://github.com/rekkyrosso/ampcast/releases) |
| [Coppelia ` ⚒️ ` ` 🎵 `](https://github.com/j6k4m8/coppelia) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/j6k4m8/coppelia/total?logo=github&label=GitHub)](https://github.com/j6k4m8/coppelia/releases) |
| [Dee Jellie ` 🎵 `](https://www.deejellie.com) | ❌ | ❌ | ☑️ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6755585736) |
| [Discrete ` 🎵 `](https://discrete.app/) | ❌ | ✅ | ☑️ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6746067740) |
| [Feishin ` ⚒️ ` ` 🎵 `](https://github.com/jeffvli/feishin) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/jeffvli/feishin/total?logo=github&label=GitHub)](https://github.com/jeffvli/feishin/releases) |
| [Finamp ` 🎵 `](https://github.com/jmshrv/finamp) | ✅ | ✅ | ❎ | [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=com.unicornsonlsd.finamp) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id1574922594) |
| [Finer ` 🎵 `](https://monk-studio.com/finer) | ❌ | ✅ | ❎ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6738301953) |
| [FinMusic ` 🎵 `](https://github.com/OHPG/FinMusic) | ✅ | ✅ | ❎ | [![AppGallery](https://img.shields.io/badge/AppGallery-grey?logo=AppGallery&label=)](https://appgallery.huawei.com/app/detail?id=org.ohpg.fin.music) [![github](https://img.shields.io/github/downloads/OHPG/FinMusic/total?logo=github&label=GitHub)](https://github.com/OHPG/FinMusic/releases) |
| [Fintunes ` 🎵 `](https://github.com/leinelissen/jellyfin-audio-player) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/leinelissen/jellyfin-audio-player/total?logo=github&label=GitHub)](https://github.com/leinelissen/jellyfin-audio-player/releases) [![F-Droid](https://img.shields.io/badge/F-Droid-grey?logo=F-Droid&label=)](https://f-droid.org/en/packages/nl.moeilijkedingen.jellyfinaudioplayer) [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=nl.moeilijkedingen.jellyfinaudioplayer) [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id1527732194) |
| [Foxy ` 🎵 `](https://github.com/Devioxic/Foxy-Desktop) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Devioxic/Foxy-Desktop/total?logo=github&label=GitHub)](https://github.com/Devioxic/Foxy-Desktop/releases) |
| [Gelli ` 🎵 `](https://github.com/dkanada/gelli) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/dkanada/gelli/total?logo=github&label=GitHub)](https://github.com/dkanada/gelli/releases) [![F-Droid](https://img.shields.io/badge/F-Droid-grey?logo=F-Droid&label=)](https://f-droid.org/packages/com.dkanada.gramophone) |
| [Gelly ` ⚒️ ` ` 🎵 `](https://github.com/Fingel/gelly) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Fingel/gelly/total?logo=github&label=GitHub)](https://github.com/Fingel/gelly/releases) [![flathub](https://img.shields.io/flathub/downloads/io.m51.Gelly?logo=Flathub&label=Flathub)](https://flathub.org/apps/io.m51.Gelly) |
| [Jellify ` 🎵 `](https://github.com/Jellify-Music/App) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Jellify-Music/App/total?logo=github&label=GitHub)](https://github.com/Jellify-Music/App/releases) [![TestFlight](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=TestFlight)](https://testflight.apple.com/join/etVSc7ZQ) |
| [Jelly Music App ` 🎵 `](https://github.com/Stannnnn/jelly-app) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Stannnnn/jelly-app/total?logo=github&label=GitHub)](https://github.com/Stannnnn/jelly-app/releases) |
| [Jellyamp ` 🎵 `](https://github.com/m0ngr31/jellyamp) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/m0ngr31/jellyamp/total?logo=github&label=GitHub)](https://github.com/m0ngr31/jellyamp/releases) |
| [Manet ` 🎵 `](https://tilo.dev/manet/) | ❌ | ✅ | ❎ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6470928235) |
| [Plappa ` 🎵 `](https://github.com/LeoKlaus/plappa) | ✅ | ✅ | ❎ | [![App Store](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=)](https://apps.apple.com/app/id6475201956) |
| [Preserve ` ⚒️ ` ` 🎵 `](https://gitlab.com/preserve/preserve) | ✅ | ✅ | ❎ | [![GitLab](https://img.shields.io/badge/GitLab-grey?logo=GitLab&label=)](https://gitlab.com/preserve/preserve) [![Demo](https://img.shields.io/badge/Web-blue?logo=&label=Demo)](https://preserveplayer.com/) |
| [Sonixd ` ⚒️ ` ` 🎵 `](https://github.com/jeffvli/sonixd) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/jeffvli/sonixd/total?logo=github&label=GitHub)](https://github.com/jeffvli/sonixd/releases) |
| [sonixd ` ⚒️ ` ` 🎵 `](https://github.com/jeffvli/sonixd) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/jeffvli/sonixd/total?logo=github&label=GitHub)](https://github.com/jeffvli/sonixd/releases) |
| [Supersonic ` ⚒️ ` ` 🎵 `](https://github.com/dweymouth/supersonic) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/dweymouth/supersonic/total?logo=github&label=GitHub)](https://github.com/dweymouth/supersonic/releases) [![flathub](https://img.shields.io/flathub/downloads/io.github.dweymouth.supersonic?logo=Flathub&label=Flathub)](https://flathub.org/apps/io.github.dweymouth.supersonic) |
| [Symfonium ` ⚒️ ` ` 🎵 `](https://symfonium.app) | ❌ | ❌ | ☑️ | [![Google Play](https://img.shields.io/badge/Google%20Play-grey?logo=Google+Play&label=)](https://play.google.com/store/apps/details?id=app.symfonik.music.player) |
| [Tauon Music Box ` 🎵 `](https://github.com/Taiko2k/TauonMusicBox) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/Taiko2k/TauonMusicBox/total?logo=github&label=GitHub)](https://github.com/Taiko2k/TauonMusicBox/releases) [![flathub](https://img.shields.io/flathub/downloads/com.github.taiko2k.tauonmb?logo=Flathub&label=Flathub)](https://flathub.org/apps/com.github.taiko2k.tauonmb) |


## ` 📖 ` Reader

| Name | OSS | Free | Paid | Downloads |
| ---- | --- | ---- | ---- | --------- |
| [JellyBook ` 📖 `](https://github.com/JellyBookOrg/JellyBook) | ✅ | ✅ | ❎ | [![github](https://img.shields.io/github/downloads/JellyBookOrg/JellyBook/total?logo=github&label=GitHub)](https://github.com/JellyBookOrg/JellyBook/releases) [![Izzysoft](https://img.shields.io/badge/-grey?logo=&label=Izzysoft)](https://apt.izzysoft.de/fdroid/index/apk/com.KaraWilson.JellyBook/) [![TestFlight](https://img.shields.io/badge/App%20Store-grey?logo=App+Store&label=TestFlight)](https://testflight.apple.com/join/lEXKY4Dl) |


---

* **Official** ` 🔹 `
* **Beta** ` ⚒️ `
* **Music Client** ` 🎵 `
* **Reader** ` 📖 `


---

> [!NOTE]
> Please note that this Markdown file is automatically generated from the [`clients.yaml`](./assets/clients/clients.yaml) file. 
> **Contributions should only be made by updating the `clients.yaml` file.** 
> Any updates to the `.yaml` file will result in this Markdown file being re-generated to reflect those changes.

<!--
⚠️ WARNING: DO NOT EDIT THIS FILE ⚠️

This Markdown file is auto-generated from the `assets/clients/clients.yaml` file. 
Any manual changes made to this file will be overwritten the next time it is generated. 
To make changes, please edit the `assets/clients/clients.yaml` file and regenerate this Markdown file.
-->

# 14. Jellyfin Themes

List of Jellyfin Themes'

**ElegantFin**: [https://lscambo13.github.io/ElegantFin/](https://lscambo13.github.io/ElegantFin/)

CSS:

```
@import url("https://cdn.jsdelivr.net/gh/lscambo13/ElegantFin@main/Theme/ElegantFin-jellyfin-theme-build-latest-minified.css");
```

# 15. Jellyfin Plugins

<!--lint disable awesome-heading awesome-toc double-link-->

<img src="/assets/banner.png" />
<blockquote align="center"> A List of Awesome Jellyfin Themes and Plugins</blockquote>

<p align="center">
[
  <a href="#-plugins">Plugins</a> •
  <a href="#-companion-apps--tools">Companion Apps & Tools</a> •
  <a href="#-guides">Guides</a> •
  <a href="#-snippets">Snippets</a> •
  <a href="#-related">Related</a> •
  <a href="#contribute">Contribute</a>
]
</p>

<table>
  <tr>
    <th width="500px" align="center">
      <h3><a href="THEMES.md">🖌️ Themes</a></h3>
      Browse the collection of community themes<br />
      <img width="1" height="10" />
    </th>
    <th width="500px" align="center">
      <h3><a href="CLIENTS.md">📺 Clients</a></h3>
      Browse available clients for all platforms<br />
      <img width="1" height="10" />
    </th>
  </tr>
</table>

## 🧩 Plugins


### 🎨 UI & Customization

<!-- sort list:plugins-ui -->
- [HoverTrailer](https://github.com/Fovty/HoverTrailer) - Displays movie trailers on hover.
- [InPlayerEpisodePreview](https://github.com/Namo2/InPlayerEpisodePreview) - Adds an episode list to the video player.
- [jellyfin-editors-choice-plugin](https://github.com/lachlandcp/jellyfin-editors-choice-plugin) - Adds a Netflix-style, full-width content slider to the home page to feature selected content.
- [Jellyfin-Enhanced](https://github.com/n00bcodr/Jellyfin-Enhanced) - Adds keyboard shortcuts, subtitle styling, TMDB reviews, Jellyseerr search and request integration, and other improvements to Jellyfin.
- [jellyfin-icon-metadata](https://github.com/Druidblack/jellyfin-icon-metadata) - Adds metadata provider icons to Jellyfin.
- [Jellyfin-JavaScript-Injector](https://github.com/n00bcodr/Jellyfin-JavaScript-Injector) - Injects custom JavaScript into the Jellyfin UI without modifying index.html.
- [Jellyfin-MonWUI-Plugin](https://github.com/G-grbz/Jellyfin-MonWUI-Plugin) - UI enhancement toolkit for Jellyfin providing customizable sliders, hover trailers, a music player, notifications, and other interface modules.
- [Jellyfin.Plugin.ActorPlus](https://github.com/Druidblack/Jellyfin.Plugin.ActorPlus) - Adds additional details and hoverable filmography to actor portraits and displays actor lists when hovering over movie or series posters.
- [jellyfin-plugin-collection-sections](https://github.com/IAmParadox27/jellyfin-plugin-collection-sections) - Adds additional sections to `jellyfin-plugin-home-sections` for collections and playlists.
- [jellyfin-plugin-custom-tabs](https://github.com/IAmParadox27/jellyfin-plugin-custom-tabs) - Adds personalized tabs in jellyfin-web for quick access to custom content.
- [jellyfin-plugin-GetAvatar](https://github.com/cedev-1/jellyfin-plugin-GetAvatar) - Allows users to choose an avatar from a collection of images.
- [jellyfin-plugin-home-sections](https://github.com/IAmParadox27/jellyfin-plugin-home-sections) - Allows users to customize the jellyfin-web home screen with dynamic sections like "Because You Watched" and "Latest Movies".
- [jellyfin-plugin-media-bar](https://github.com/IAmParadox27/jellyfin-plugin-media-bar) - A Featured Content Bar to showcase your media collection.
- [jellyfin-plugin-pages](https://github.com/IAmParadox27/jellyfin-plugin-pages) - Enables other plugins to create custom Jellyfin pages that match the native UI.
- [jellyfin-plugin-ratings](https://github.com/K3ntas/jellyfin-plugin-ratings) - Adds user ratings, card overlays, media requests, deletion workflows, chat, and new media notifications to Jellyfin.
- [jellyfin-plugin-skin-manager](https://github.com/danieladov/jellyfin-plugin-skin-manager) - Helps you to download and install skins.
- [Jellyfin-Seasonals](https://github.com/CodeDevMLH/Jellyfin-Seasonals) - Collections of seasonal themes and animations for Jellyfin.
- [jellyscrub](https://github.com/nicknsy/jellyscrub) - Smooth mouse-over video scrubbing previews. `🔸 Stale`
  <!--lint ignore list-item-indent awesome-list-item-->
    -  **NOTE:** Jellyfin 10.9 now natively supports trickplay.
- [Static Assets](https://github.com/cleverdevil/jelly-static-assets) - Upload and serve static assets such as CSS, JavaScript, and images directly from Jellyfin. `🔸 Stale`


### 📂 Collections & Playlists

<!-- sort list:plugins-collections -->
- [jellyfin-favorited-songs-playlist](https://github.com/Saturn745/jellyfin-favorited-songs-playlist) - Automatically creates and updates a "Favorited Songs" playlist containing all your favorited music tracks.
- [jellyfin-plugin-auto-collections](https://github.com/KeksBombe/jellyfin-plugin-auto-collections) - Automatically creates and maintains dynamic collections based on flexible criteria.
- [jellyfin-plugin-collection-import](https://github.com/lostb1t/jellyfin-plugin-collection-import) - Creates and sorts collections by importing from external sources like *mdblist*.
- [jellyfin-plugin-provider-stuff](https://github.com/kamilkosek/jellyfin-plugin-provider-stuff) - Automates tagging library items with streaming provider tags, creates collections per provider. `🔸 Stale`
- [Jellyfin-Roulette](https://github.com/ztffn/Jellyfin-Roulette) - Adds a roulette feature that plays a random entry from a playlist.
- [jellyfin-smartlists-plugin](https://github.com/jyourstone/jellyfin-smartlists-plugin) - Creates dynamic collections and playlists in Jellyfin that automatically update based on customizable rules as the library changes.
- [playlist-generator](https://github.com/Eeeeelias/playlist-generator) - Creates personal playlists based on your listening history.
- [TheDwarfsHammer](https://github.com/Kamoba/jellyfin-plugin-thedwarfshammer) - Enhanced collection management and content discovery for Jellyfin.


### ▶️ Playback

<!-- sort list:plugins-playback -->
- [intro-skipper](https://github.com/intro-skipper/intro-skipper) - Fingerprint audio to automatically detect intro and outro segments in Jellyfin.
- [jellyfin-plugin-cinemamode](https://github.com/CherryFloors/jellyfin-plugin-cinemamode) - Enables Jellyfin's Cinema Mode with local trailers and pre-rolls.
- [jellyfin-plugin-discontinue-watching](https://github.com/jon4hz/jellyfin-plugin-discontinue-watching) - Lets you remove items from the Continue Watching list without resetting watch progress, with optional auto-hide after inactivity.
- [jellyfin-plugin-jellysleep](https://github.com/jon4hz/jellyfin-plugin-jellysleep) - Adds sleep timer functionality to Jellyfin.
- [Jellyfin.Plugin.StreamLimit](https://github.com/JellyboxAD/Jellyfin.Plugin.StreamLimit) - Allows limiting the number of simultaneous streams per user.
- [jellyfin-transcode-nag](https://github.com/voc0der/jellyfin-transcode-nag) - Nags users when they're transcoding due to unsupported formats or codecs, while allowing bitrate-based transcoding.


### 🔗 Integration & Sync

<!-- sort list:plugins-integration -->
- [Gelato](https://github.com/lostb1t/Gelato) - Replaces Jellyfin's default search with Stremio-powered results and can automatically import entire catalogs into your library through scheduled tasks.
- [jellyfin-ani-sync](https://github.com/vosmiic/jellyfin-ani-sync) - Automatically tracks and synchronizes anime watching progress between Jellyfin and [Anilist](https://anilist.co/) and other services.
- [jellyfin-plugin-animethemes](https://github.com/EusthEnoptEron/jellyfin-plugin-animethemes) - Fetches anime opening and ending themes from [AnimeThemes.moe](https://animethemes.moe/), supporting both audio and video.
- [Jellyfin.Plugin.JF_To_Stash_Sync](https://github.com/Druidblack/Jellyfin.Plugin.JF_To_Stash_Sync) - Synchronizes viewing activity with Stash.
- [jellyfin-plugin-letterboxd-sync](https://github.com/Gizmo091/jellyfin-plugin-letterboxd-sync) - Automatically syncs your watched movie history with Letterboxd.
- [jellyfin-plugin-listenbrainz](https://github.com/lyarenei/jellyfin-plugin-listenbrainz) - Automatically syncs your music activity with ListenBrainz.
- [jellyfin-plugin-streamyfin](https://github.com/streamyfin/jellyfin-plugin-streamyfin) - Companion plugin for Streamyfin which allows for a centralized configuration of the Streamyfin application.
- [jellyfin-rpc by *kennethsible*](https://github.com/kennethsible/jellyfin-rpc) - Displays your current Jellyfin activity directly on Discord.
- [jellyfin-rpc by *Radiicall*](https://github.com/JustRadical/jellyfin-rpc) - Displays your current Jellyfin activity directly on Discord.
- [jellynext](https://github.com/luall0/jellynext) - Creates per-user virtual libraries for personalized Trakt recommendations and new seasons.
- [Moonbase](https://github.com/Moonfin-Client/Plugin) - Companion plugin for Moonfin clients, providing server-side settings sync, integrations, and a hosted Moonfin Web interface.
- [MyAnimeSync](https://github.com/iankiller77/MyAnimeSync) - Automatically synchronizes anime watching progress between Jellyfin and MyAnimeList.
- [Plexyfin](https://github.com/cleverdevil/plexyfin) - Automatically synchronizes artwork and collections from Plex to Jellyfin.
- [Shokofin](https://github.com/ShokoAnime/Shokofin) - Integrates [Shoko Server](https://shokoanime.com/downloads/shoko-server/) with Jellyfin for anime library management.


### 🔔 Notifications

<!-- sort list:plugins-notifications -->
- [Jellyfin-Newsletter](https://github.com/Sanidhya30/Jellyfin-Newsletter) - Sends newsletters and notifications about library changes (additions, updates, deletions) via email, Discord, or Telegram.
- [Jellyfin-Newsletter-Plugin](https://github.com/Cloud9Developer/Jellyfin-Newsletter-Plugin) - Newsletters for recently added media. `🔹 Beta`
- [jellyfin-plugin-DiscordNotifier](https://github.com/cedev-1/jellyfin-plugin-DiscordNotifier) - Sends notifications of Jellyfin server events to Discord.
- [jellyfin-plugin-TelegramNotifier](https://github.com/RomainPierre7/jellyfin-plugin-TelegramNotifier) - Receive notifications of Jellyfin server events via Telegram.
- [NotifySync](https://github.com/peterdu1109/NotifySync) - Adds a notification bell to Jellyfin that displays recent additions.


### 🔐 Authentication

<!-- sort list:plugins-auth -->
- [jellyfin-plugin-ldapauth](https://github.com/jellyfin/jellyfin-plugin-ldapauth) - Allows the use of LDAP as an auth provider.
- [jellyfin-plugin-sso](https://github.com/9p4/jellyfin-plugin-sso) - Allows users to sign in through an SSO provider. `🔹 Beta`
- [Jellyfin Security](https://github.com/ZL154/JellyfinSecurity) - Natively adds TOTP and email 2FA, passkeys, OIDC/SSO sign-in, brute-force protection, IP allowlists, device pairing, trusted browsers, and audit logging to Jellyfin.
- [TeleJelly](https://github.com/hexxone/TeleJelly) - Allows users to sign in through the [Telegram Login Widget](https://core.telegram.org/widgets/login).


### 📚 Library Management

<!-- sort list:plugins-library -->
- [AniLiberty STRM Plugin](https://github.com/queukat/AniLibriaStrmPlugin) - Generates AniLiberty STRM libraries for Jellyfin with metadata, intro markers, and watch-progress sync.
- [Jellyfin Ignore](https://github.com/fdett/jellyfin-ignore/) - Ignores filename patterns on library scans. `🔹 Beta` `🔸 Stale`
- [jellyfin-local-posters](https://github.com/NooNameR/Jellyfin.Plugin.LocalPosters/) - Automatically matches and imports local posters using TPDb and MediUX filename formats. Also supports syncing posters from Google Drive.
- [jellyfin-musictags-plugin](https://github.com/jyourstone/jellyfin-musictags-plugin) - Automatically extracts audio file metadata and converts it into standard Jellyfin tags.
- [jellyfin-plugin-air-times](https://github.com/k0d13/jellyfin-air-times) - Provides localized series air times based on server location. `🔸 Stale`
- [jellyfin-plugin-enigma2](https://github.com/knackebrot/jellyfin-plugin-enigma2) - Supports Vu+ & Enigma2 live TV streamers. `🔸 Stale`
- [jellyfin-plugin-languageTags](https://github.com/TheXaman/jellyfin-plugin-languageTags) - Adds language tags to media based on audio tracks using FFmpeg.
- [jellyfin-plugin-localrecs](https://github.com/rdpharr/jellyfin-plugin-localrecs) - Generates personalized movie and TV recommendations based on local watch history without external services required.
- [jellyfin-plugin-media-cleaner](https://github.com/shemanaev/jellyfin-plugin-media-cleaner) - Automatically removes played media after a specified time period.
- [jellyfin-plugin-MediathekViewDL](https://github.com/CatNoir2006/jellyfin-plugin-MediathekViewDL) - Integrates MediathekViewDL into Jellyfin and allows users to search, download, and manage content.
- [jellyfin-plugin-meilisearch](https://github.com/arnesacnussem/jellyfin-plugin-meilisearch) - Enhances Jellyfin search speed and accuracy by offloading queries to a Meilisearch instance.
- [jellyfin-powertoys](https://github.com/lennykean/jellyfin-powertoys) - A collection of plugins to enhance Jellyfin with additional features and tools.
- [JellyfinTweaks](https://github.com/n00bcodr/JellyfinTweaks) - Overrides Jellyfin settings such as *Enable Backdrops* and *Enable Theme Music* across all devices.
- [Jellyfin-Xtream-Library](https://github.com/firestaerter3/Jellyfin-Xtream-Library) - Syncs Xtream VOD and Series content to native Jellyfin libraries via STRM files, with automatic metadata lookup and Live TV support.
- [JellySTRMprobe](https://github.com/firestaerter3/JellySTRMprobe) - Probes STRM files to extract media information (codec, resolution, duration, audio) that Jellyfin skips during library scans.
- [media-upload-plugin](https://github.com/GrandguyJS/media-upload-plugin) - Media-manager that provides uploads, bulk downloads from URLs, and directory browsing within Jellyfin. `🔸 Stale`
- [quality-gate](https://github.com/GeiserX/quality-gate) - Restrict users to specific media versions based on configurable path-based policies, useful for bandwidth management or tiered access.
- [smart-covers](https://github.com/GeiserX/smart-covers) - Cover extraction for books, audiobooks, comics, magazines, and music libraries with online fallback via Open Library & Google Books.
- [whisper-subs](https://github.com/GeiserX/whisper-subs) - Automatically generates subtitles using local AI models powered by Whisper, with all processing on your server.


### 🏷️ Metadata Providers

<!-- sort list:metadata-providers -->
- [jellyfin-imdb-rating-updater](https://github.com/voc0der/jellyfin-imdb-rating-updater) - Downloads the IMDb ratings dataset daily and updates the CommunityRating field for library items with an IMDb ID without modifying other metadata.
- [jellyfin-plugin-AnimeMultiSource](https://github.com/webbster64/jellyfin-plugin-AnimeMultiSource) - Aggregates anime metadata, tags, artwork, and people from multiple sources (AniList, AniDB, MAL/Jikan, TVDB, Fanart.tv) with rate limiting and persistent caching for large libraries.
- [jellyfin-plugin-applemusic](https://github.com/lyarenei/jellyfin-plugin-applemusic) - Fetches album and artist metadata from Apple Music.
- [Jellyfin.Plugin.ArtworkMultiSource](https://github.com/Druidblack/Jellyfin.Plugin.ArtworkMultiSource) - Combines posters and logos from TMDb and TVDB with language-aware priority and configurable sorting.
- [jellyfin-plugin-hikka](https://github.com/HotMasya/jellyfin-plugin-hikka) - Metadata and images for anime and manga from the Hikka website.
- [jellyfin-plugin-kinopoisk](https://github.com/LinFor/jellyfin-plugin-kinopoisk) - Metadata provider for [Kinopoisk](https://www.kinopoisk.ru/).
- [Jellyfin.Plugin.MDBList_Ratings](https://github.com/Druidblack/Jellyfin.Plugin.MDBList_Ratings) - Retrieves ratings from MDBList using TMDb IDs and integrates them into Jellyfin's rating fields, with optional UI enhancements to display ratings from multiple sources.
- [jellyfin-plugin-myanimelist](https://github.com/ryandash/jellyfin-plugin-myanimelist) - Provides MyAnimeList metadata for anime.
- [jellyfin-plugin-onepace](https://github.com/jwueller/jellyfin-plugin-onepace) - Provides metadata and cover art for the [One Pace](https://onepace.net) project.
- [Jellyfin Plugin PhoenixAdult](https://github.com/DirtyRacer1337/Jellyfin.Plugin.PhoenixAdult) - Metadata provider for adult content from multiple sites. `🔸 Stale`
- [jellyfin-plugin-shikimori](https://github.com/te9c/jellyfin-plugin-shikimori) - Metadata provider for shikimori.one.
- [Jellyfin Plugin Stash](https://github.com/DirtyRacer1337/Jellyfin.Plugin.Stash) - Metadata provider for [Stash](https://github.com/stashapp/stash).
- [Jellyfin Plugin ThePornDB](https://github.com/ThePornDatabase/Jellyfin.Plugin.ThePornDB) - Metadata provider for ThePornDB.
- [jellyfin-youtube-metadata-plugin](https://github.com/ankenyr/jellyfin-youtube-metadata-plugin) - Provides metadata for YouTube content.


## 👾 Companion Apps & Tools


### 🖼️ Artwork & Posters

<!-- sort list:tools-artwork -->
- [aphrodite](https://github.com/jackkerouac/aphrodite) - Enhances media library posters with quality indicators like resolution, audio codec, and review ratings. `🔸 Stale`
- [CoverMaker](https://github.com/jeffersoncgo/CoverMaker) - Allows designing and generating custom cover images for your media collections.
- [Jellyfin-Cover-Maker](https://github.com/KartoffelChipss/Jellyfin-Cover-Maker) - Website for creating consistent covers and posters for Jellyfin libraries.
- [Jellyfin-Image-Exporter](https://github.com/Kurotaku-sama/Jellyfin-Image-Exporter) - Exports images (posters, banners, thumbnails) from Jellyfin metadata.
- [jellyfin-poster-hrd-logo](https://github.com/Druidblack/jellyfin-poster-hrd-logo/tree/main) - Automatically downloads covers for HDR movies from TMDb and applies an HDR logo in the top-right corner. `🔸 Stale`
- [jellyfin_ratings](https://github.com/Druidblack/jellyfin_ratings) - Replaces Jellyfin ratings with ratings from various sources (IMDb, Trakt, Letterboxd, and others).
- [jellyfin-tools](https://github.com/eebette/jellyfin-tools) - Generates images with Jellyfin-like styling such as shadow overlays and library title text. `🔸 Stale`
- [Jellyfin Update Poster](https://github.com/Iceshadow1404/JellyfinUpdatePoster) - Batch imports cover images from [ThePosterDB](https://theposterdb.com/) and [MediUX](https://mediux.pro), with set downloading support for MediUX.
- [jellytools](https://github.com/cleverdevil/jellytools) - CLI tool for synchronizing artwork and collections from Plex to Jellyfin and generating animated library card videos. `🔸 Stale`
- [pixelfin](https://github.com/nothing2obvi/pixelfin) - Inspects Jellyfin libraries for missing, present, or low-resolution images with export support.
- [Posterizarr](https://github.com/fscorrupt/posterizarr) - Automates poster, background, and title card creation for Plex, Jellyfin, and Emby with customizable overlays.
- [TitleCardMaker](https://github.com/CollinHeist/TitleCardMaker) - Automated title card maker for Plex, Jellyfin, and Emby.


### 🔍 Media Requests & Discovery

<!-- sort list:tools-requests -->
- [Anchorr](https://github.com/openVESSL/Anchorr) - Discord bot for Jellyfin media requests and new content notifications.
- [AudioBookRequest](https://github.com/markbeep/AudioBookRequest) - Request management tool for audiobooks on Plex, Jellyfin, and Audiobookshelf.
- [content-recommender](https://github.com/jeffersoncgo/content-recommender) - Suggests movies or TV shows from your library based on watch history.
- [jellyfin-updoot](https://github.com/BobHasNoSoul/jellyfin-updoot) - Adds thumbs-up recommendations, per-item comments, and a "recommended by users" page.
- [jellyseerr](https://github.com/seerr-team/seerr) - Request management and media discovery tool for Jellyfin, Plex, and Emby.
- [List-Sync](https://github.com/Woahai321/list-sync) - Automatically import movies and TV shows from IMDB or Trakt lists into [Jellyseerr](https://github.com/seerr-team/seerr). `🔹 Beta`
- [reiverr](https://github.com/aleksilassila/reiverr) - Combined interface for Jellyfin, TMDB, Radarr, and Sonarr. `🔹 Beta`
- [scenepeek-android](https://github.com/Divinelink/scenepeek-android) - An Android app that provides detailed movie and TV show information with TMDB and Jellyseerr integration.
- [SuggestArr](https://github.com/giuseppe99barchetta/SuggestArr) - Automatically request suggested movies and TV shows to [Jellyseerr](https://github.com/seerr-team/seerr) based on recently watched.
- [swiparr](https://github.com/m3sserstudi0s/swiparr) - Swipe through your library, match with friends in a session, and find something everyone wants to watch.
- [whatseerr](https://github.com/SuFxGIT/whatseerr) - WhatsApp bot for Seerr that allows users to search and request media via WhatsApp messages.


### 📊 Statistics & Watch History

<!-- sort list:tools-stats -->
- [jellyfin-rewind](https://github.com/Chaphasilor/jellyfin-rewind) - A *Spotify Wrapped*-like experience for Jellyfin music listeners.
- [jellyfin-watch-updater](https://github.com/Simon-Eklundh/jellyfin-watch-updater) - Updates `lastPlayedDate` for watched items when clients fail to set it, enabling tools such as media cleanup plugins to correctly detect watched media.
- [JellyPlex-Watched](https://github.com/luigi311/JellyPlex-Watched) - Syncs watch history between Jellyfin, Plex, and Emby Servers.
- [Jellystat](https://github.com/CyferShepard/Jellystat) - Statistics and analytics dashboard for Jellyfin.
- [jelly-watch-wise](https://github.com/Joker-KP/jelly-watch-wise) - Monitors and enforces Jellyfin watch time limits per user, with API integration and a simple GUI. `🔸 Stale`
- [streamystats](https://github.com/fredrikburmester/streamystats) - Statistics service for Jellyfin, providing analytics and data visualization.
- [watchstate](https://github.com/arabcoders/watchstate) - Syncs play state between different media servers.


### 👥 User Management

<!-- sort list:tools-users -->
- [Jellycord](https://github.com/SiddheshDongare/Jellycord) - Discord companion bot for managing JFA-GO instances. `🔸 Stale`
- [jellyfin-telegram-channel-sync](https://github.com/GeiserX/jellyfin-telegram-channel-sync) - Syncs Jellyfin user access with Telegram channel membership, automatically disabling accounts when members leave.
- [jfa-go](https://github.com/hrfee/jfa-go) - User- / Invite-Management system for Jellyfin.
- [jf-avatars](https://github.com/kalibrado/jf-avatars) - Allows users to select avatars from an image gallery.
- [wizarr](https://github.com/wizarrrr/wizarr) - Advanced user invitation and management system.


### 📁 Media Organization

<!-- sort list:tools-organization -->
- [CineSync](https://github.com/sureshfizzy/CineSync) - Python-based library management tool for organizing debrid and local libraries without Sonarr or Radarr.
- [Fixarr](https://github.com/sachinsenal0x64/fixarr) - Cross-platform media renaming and backup tool. `🔹 Beta`
- [JellyCC](https://github.com/parkejunior/jellycc-cli) - Command-line tool that audits, repairs and optimizes media to ensure Direct Play on Jellyfin. 
- [Jellyfin-Auto-Collections](https://github.com/ghomasHudson/Jellyfin-Auto-Collections) - A tool to automatically make and update collections based on internet lists such as IMDb and Letterboxd.
- [JellyfinEasyMetadataManager](https://github.com/CesarBianchi/JellyfinEasyMetadataManager) - Desktop tool for managing and editing metadata in Jellyfin libraries.
- [jellyfinmanager](https://github.com/Forceu/jellyfinmanager) - Command-line tool for managing Jellyfin watched status with backup/restore capabilities and missing episode detection using TVDB.
- [jellysweep](https://github.com/jon4hz/jellysweep) - Automatically removes old, unwatched movies and TV shows by analyzing viewing history and user requests.
- [mnamer](https://github.com/jkwill87/mnamer) - Customizable tool to automatically rename and organize media files.
- [Multi-User Media Cleaner](https://github.com/terrelsa13/MUMC) - Query and delete unwanted media content from your Jellyfin server.
- [Squishy](https://github.com/cleverdevil/squishy) - Transcode and download your Jellyfin media with fully customizable presets and hardware acceleration.


### 💬 Subtitles

<!-- sort list:tools-subtitles -->
- [bazarr-jellyfin](https://github.com/enoch85/bazarr-jellyfin) - Search and download subtitles directly from Jellyfin's native subtitle UI using your Bazarr instance.
- [OpenSubtitlesDownload](https://github.com/emericg/OpenSubtitlesDownload) - Automatically or manually downloads subtitles using CLI/Gnome/KDE.
- [subgen](https://github.com/McCloudS/subgen) - Autogenerate subtitles using OpenAI Whisper Model via Jellyfin.


### 🎵 Music

<!-- sort list:tools-music -->
- [AudioMuse-AI](https://github.com/NeptuneHub/AudioMuse-AI) - Uses sonic analysis and AI-powered clustering to create tempo and mood-based playlists via the Jellyfin API.
- [jellyfin-theme-music-manager](https://github.com/akhilmulpurii/jellyfin-theme-music-manager) - Web application for managing theme songs and backdrop videos for Jellyfin libraries.
- [jellyplist](https://github.com/kamilkosek/jellyplist) - Utility for syncing Spotify playlists to Jellyfin. `🔹 Beta`
- [JellyTunes](https://github.com/oriaflow-labs/jellytunes) - Sync your Jellyfin music library to any USB drive or SD card — with optional FLAC to MP3 conversion.
- [MusicBrainz-UserScripts](https://github.com/Druidblack/MusicBrainz-UserScripts) - One-click importing of album from Jellyfin into MusicBrainz.
- [Playlifin](https://gitlab.com/Krafting/playlifin-gtk) - Converts YouTube Music playlists to Jellyfin playlists.


### 📥 Content Import

<!-- sort list:tools-import -->
- [calibre2jellyfin](https://github.com/shawn61cp/calibre2jellyfin) - Python script to construct a Jellyfin ebook library from a Calibre library.
- [trailarr](https://github.com/nandyalu/trailarr) - Manages trailer downloads for your Radarr and Sonarr libraries.
- [trailerfin](https://github.com/Pukabyte/trailerfin) - Automatically retrieves and creates STRM links to IMDb trailers and places them in the backdrops folder to view trailers on the details page.
- [ytdlp2STRM](https://github.com/fe80Grau/ytdlp2STRM) - Streams YouTube, Twitch and more via yt-dlp to Jellyfin.
- [ytdl-sub](https://github.com/jmbannon/ytdl-sub) - Automates downloading and metadata generation with yt-dlp.


### 🔧 Server Administration

<!-- sort list:tools-admin -->
- [ADRG](https://github.com/jaldertech/adrg) - Dynamic Docker resource governor using cgroups v2 to throttle background tasks during media activity.
- [autopulse](https://github.com/dan-online/autopulse) - Lightweight automation service that updates Plex, Jellyfin, and Emby libraries based on notifications from media organizers like Sonarr and Radarr.
- [autoscan](https://github.com/Cloudbox/autoscan) - Replaces the default Plex and Emby behaviour for picking up changes on the file system. `🔸 Stale`
- [Cloud Seeder](https://github.com/ipv6rslimited/cloudseeder) - One-click installer and maintainer for Jellyfin on Windows, macOS, and Linux.
- [declarative-jellyfin](https://github.com/Sveske-Juice/declarative-jellyfin) - Declarative configuration of your Jellyfin server on NixOS. `🔹 Beta`
- [jellyfin-encoder](https://github.com/GeiserX/jellyfin-encoder) - Docker-based automatic 720p HEVC/AV1 transcoding service for Jellyfin libraries with NVIDIA and Intel hardware acceleration.
- [jellyhub](https://github.com/Zigl3ur/jellyhub) - Indexes media from multiple Jellyfin servers into a single searchable hub.
- [Jellyman](https://github.com/Smiley-McSmiles/jellyman) - CLI tool for installing, managing, and updating Jellyfin on Linux.
- [JellyRoller](https://github.com/LSchallot/JellyRoller) - A CLI Jellyfin Controller. `🔹 Beta`
- [JellySearch](https://gitlab.com/DomiStyle/jellysearch) - A fast full-text search proxy for Jellyfin using Meilisearch.
- [Jellyswarrm](https://github.com/LLukas22/Jellyswarrm) - Reverse proxy that lets you combine multiple Jellyfin servers into one virtual instance.
- [Samsung-Jellyfin-Installer](https://github.com/Jellyfin2Samsung/Samsung-Jellyfin-Installer) - Cross-platform tool that helps you install Jellyfin on Samsung Smart TVs running Tizen OS.
- [Universal Plugin Repo](https://github.com/0belous/universal-plugin-repo) - Consolidates many plugin repositories to create a universal catalogue.
- [xsrv.jellyfin](https://github.com/nodiscc/xsrv/tree/master/roles/jellyfin) - Ansible role to deploy and configure Jellyfin.


### 🧰 Miscellaneous

<!-- sort list:tools-misc -->
- [embyToLocalPlayer](https://github.com/kjtsune/embyToLocalPlayer) - Lets you watch videos from Jellyfin using a local video player (like VLC and MPV) and syncs watch progress back.
- [jelly-clipper](https://github.com/arnolicious/jelly-clipper) - Web application for creating, sharing, and managing video clips from Jellyfin libraries. `🔹 Beta`
- [Jellyfin Episodes Ratings Grid](https://github.com/Damocles-fr/jellyfin-imdb-episodes-heatmap-ratings-grid) - Show IMDb episode ratings in a heatmap-style grid on Jellyfin series pages.
- [jellyfin-mods](https://github.com/BobHasNoSoul/jellyfin-mods) - Collection of modifications and customizations for personalizing Jellyfin.
- [Jellyfin Notification System](https://github.com/Fahmula/jellyfin-telegram-notifier) - Sends Telegram notifications with media images whenever a new movie, series, season, or episode is added to Jellyfin. `🔸 Stale`
- [Jellyfin Segment Editor](https://github.com/intro-skipper/segment-editor) - Manage Jellyfin Media Segment positions.
- [KefinTweaks](https://github.com/ranaldsgift/KefinTweaks) - Collection of UI enhancements and customization tweaks for Jellyfin.
- [MPC-JF](https://github.com/Damocles-fr/MPC-JF) - Launch external media players (MPC-HC, MPC-BE, PotPlayer) from Jellyfin Web or Jellyfin Media Player.
- [Scyphomote](https://github.com/eiffelbeef/scyphomote) - A dedicated remote control for Jellyfin with support for playback transparency, trickplay previews, and more.
- [tunarr](https://github.com/chrisbenincasa/tunarr) - Create custom live TV channels from your Plex or Jellyfin library with a web UI and IPTV support.


### 📜 Snippets

<!--lint ignore awesome-list-item-->
- [snippets/language-overlay](snippets/language-overlay) - A script to add flags to movie posters.


## 📖 Guides

<!-- sort list:guides -->
- [jellyfin-on-macos](https://github.com/Digital-Shane/jellyfin-on-macos) - Guide for hosting Jellyfin on macOS with dynamic DNS, geo-filtering, and monitoring dashboards.

## 🌌 Related

This section includes software, guides and tools that are not *specifically* designed to work with Jellyfin, but can be useful for tasks related to media management or to enhance Jellyfin's functionality.

<!-- sort list:related -->
- [Dispatcharr](https://github.com/Dispatcharr/Dispatcharr) - Self-hosted M3U proxy with IPTV, EPG, and VOD management support.
- [ErsatzTV](https://github.com/ErsatzTV/ErsatzTV) - Stream custom live channels using your own media. `🔹 Beta`
- [Explo](https://github.com/LumePart/Explo) - Automated music discovery tool that recommends tracks based on your listening history.
- [locatarr](https://github.com/Locatarr/locatarr.github.io) - A list of tools used to automate the downloading and organization of media files.
    - [radarr](https://github.com/Radarr/Radarr) - Automates downloading & management of movies.
    - [sonarr](https://github.com/Sonarr/Sonarr) - Automates downloading & management of TV series.
    - [tdarr](https://github.com/HaveAGitGat/Tdarr) - Distributed transcode automation + Library analytics + Video health checking. `🔺 Paid`
    - [recyclarr](https://github.com/recyclarr/recyclarr) - Automatically sync TRaSH guides to Sonarr and Radarr instances.
- [MediaTracker](https://github.com/bonukai/MediaTracker) - Media tracker and user rating platform with [Jellyfin integration](https://github.com/bonukai/jellyfin-plugin-mediatracker).
- [Movary](https://github.com/leepeuker/movary) - Media tracker and user rating platform. `🔹 Beta`
- [Multi Scrobbler](https://github.com/FoxxMD/multi-scrobbler) - Scrobbles music from many sources to many clients. `🔹 Beta`
- [Quasarr](https://github.com/rix1337/Quasarr) - Emulates a usenet indexer and download client to allow direct downloads with sonarr/radarr.
- [rffmpeg](https://github.com/joshuaboniface/rffmpeg) - A remote FFmpeg wrapper, commonly used for transcoding media on more capable machines.
- [speedrr](https://github.com/itschasa/speedrr) - Change your torrent client's upload speed dynamically, on certain events such as when a Plex/Jellyfin stream starts.
- [Threadfin](https://github.com/Threadfin/Threadfin) - M3U proxy for Jellyfin (Based on xTeVe).
- [TRaSH Guides](https://trash-guides.info/) - Easy-to-understand guides for Sonarr, Radarr, and Bazarr, along with related tools.

## Communities

This section contains links to communities which focus on Jellyfin or related topics.

<!-- list:communities -->
- [Jellyfin Discord](https://discord.gg/zHBxVSXdBV) - The official Jellyfin Discord server. `🔰 Official`
- [Jellyfin Forum](https://forum.jellyfin.org/) - The official Jellyfin forum. `🔰 Official`
- [Jellyfin Matrix](https://matrix.to/#/#jellyfinorg:matrix.org) - The official Jellyfin Matrix server. `🔰 Official`
- [r/Jellyfin](https://www.reddit.com/r/jellyfin/) - The official Jellyfin subreddit. `🔰 Official`
- [r/JellyfinCommunity](https://www.reddit.com/r/JellyfinCommunity/) - An independent, community-run subreddit.
- [JellyfinCommunity Discord](https://discord.gg/MTM8dkjr93) - An independent, community-run Discord server.

## Contribute

Contributions welcome! But please read the [contribution guidelines](CONTRIBUTING.md) first.
You can also [create a new issue](https://github.com/awesome-jellyfin/awesome-jellyfin/issues/new).

# 16. Jellyfin Enhanced

**Reboot:** It is important that after installing Jellyfin Enhanced that you reboot the whole Jellyfin stack. Just a simple reboot from the dashboard screen won't work. Hence, go to Dockhand and reboot the whole stack, from the cli or any other docker configuration software that you are using. After the reboot you will notice that at least a random item button will appear in the right top corner

# 1.5.18 Cal.com

# 1.5.19 Kurier

# 1.5.20 ArchiveTune Music

<span>Source: </span>[https://github.com/ArchiveTuneApp/ArchiveTune](https://github.com/ArchiveTuneApp/ArchiveTune)

This is not a self hosted app, but it is perfect to replace spotify and itunes with.

# 1.5.21 OpenCut

Source: https://opencut.app/roadmap

# 1.5.22 Sure Finance

[Sure](https://sure.am)<span> is an all-in-one personal finance platform. Track, optimize, grow, and manage your money through every stage of life.</span>

# 01. What is Sure Finance ?

### Track your <span class="text-gray-900">bank accounts </span> ![bank logos](https://sure.am/assets/home-add-anything-bank-accounts-781fdc2a.svg) , check how your <span class="text-gray-900">stocks</span> ![stock logos](https://sure.am/assets/home-add-anything-stocks-3befdc03.svg) and <span class="text-gray-900">crypto </span> ![crypto logos](https://sure.am/assets/home-add-anything-crypto-0d8a6825.svg) are doing, and monitor your <span class="text-gray-900">everything</span> else ![credit card logos](https://sure.am/assets/home-add-anything-assets-762c5301.svg) in any <span class="text-gray-900">currency</span> ![currency logos](https://sure.am/assets/home-add-anything-currency-51b795a3.svg) all in one place.

<span class="font-semibold">Alright! Well yeah we still live in a capitalistic world and hence our finances have a big impact on our lives and the time we can spend on open source projects ;) Hence, a great open source project called Sure can help you organizing your financial life. It basically handles all your assets in one central place. That includes values of all your assets, cash and bank accounts. This can be interestingly handy if you want to have one glass that displays everything instead of having multiple apps, accounts and dashboards you need to go through to keep track of all your finances. It can both be used for families and personal accounts but as well for small businesses.</span>

###   

# 02. Installation

Sure provides a great installation page on their [website](https://docs.sure.am/self-hosting) as can be found over here. However, I would like to drop the docker compose file straight away. Also note that I like to keep all the volumes inside the same folder instead of all in docker volumes. Hence, this has been changed compared to the original docker [compose file](https://docs.sure.am/self-hosting). We will deploy this again nicely in Dockhand with compose and .env file that can be found below

<details id="bkmrk-compose.yml-x-db-env"><summary>compose.yml</summary>

```
x-db-env: &db_env
  POSTGRES_USER: ${POSTGRES_USER:-sure_user}
  POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-sure_password}
  POSTGRES_DB: ${POSTGRES_DB:-sure_production}

x-rails-env: &rails_env
  <<: *db_env
  SECRET_KEY_BASE: ${SECRET_KEY_BASE:-a7523c3d0ae56415046ad8abae168d71074a79534a7062258f8d1d51ac2f76d3c3bc86d86b6b0b307df30d9a6a90a2066a3fa9e67c5e6f374dbd7dd4e0778e13}
  SELF_HOSTED: "true"
  RAILS_FORCE_SSL: "false"
  RAILS_ASSUME_SSL: "false"
  DB_HOST: db
  DB_PORT: 5432
  REDIS_URL: redis://redis:6379/1
  # NOTE: enabling OpenAI will incur costs when you use AI-related features in the app (chat, rules).  Make sure you have set appropriate spend limits on your account before adding this.
#  OPENAI_ACCESS_TOKEN: ${OPENAI_ACCESS_TOKEN}

services:
  web:
    image: ghcr.io/we-promise/sure:stable
    volumes:
      - ./app-storage:/rails/storage
    ports:
      - ${PORT:-3000}:3000
      # To also publish on IPv6 (dual-stack), uncomment the line below AND
      # set BINDING=:: in the environment block. See docs/hosting/docker.md
      # "Binding to IPv6" for details.
      # - "[::]:${PORT:-3000}:3000"
    restart: unless-stopped
    environment:
      <<: *rails_env
      # BINDING: "::"  # Uncomment for IPv6 dual-stack inside the container
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    dns:
      - 8.8.8.8
      - 1.1.1.1
    networks:
      - sure_net

  worker:
    image: ghcr.io/we-promise/sure:stable
    command: bundle exec sidekiq
    volumes:
      - ./app-storage:/rails/storage
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    dns:
      - 8.8.8.8
      - 1.1.1.1
    environment:
      <<: *rails_env
    networks:
      - sure_net

  db:
    image: postgres:16
    restart: unless-stopped
    volumes:
      - ./postgres-data:/var/lib/postgresql/data
    environment:
      <<: *db_env
    healthcheck:
      test: [ "CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB" ]
      interval: 5s
      timeout: 5s
      retries: 5
    networks:
      - sure_net

  backup:
    profiles:
      - backup
    image: prodrigestivill/postgres-backup-local
    restart: unless-stopped
    volumes:
      - ./backups:/backups # Change this path to your desired backup location on the host machine
    environment:
      - POSTGRES_HOST=db
      - POSTGRES_DB=${POSTGRES_DB:-sure_production}
      - POSTGRES_USER=${POSTGRES_USER:-sure_user}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-sure_password} # pipelock:ignore
      - SCHEDULE=@daily # Runs once a day at midnight
      - BACKUP_KEEP_DAYS=7 # Keeps the last 7 days of backups
      - BACKUP_KEEP_WEEKS=4 # Keeps 4 weekly backups
      - BACKUP_KEEP_MONTHS=6 # Keeps 6 monthly backups
    depends_on:
      - db
    networks:
      - sure_net

  redis:
    image: redis:latest
    restart: unless-stopped
    volumes:
      - ./redis-data:/data
    healthcheck:
      test: [ "CMD", "redis-cli", "ping" ]
      interval: 5s
      timeout: 5s
      retries: 5
    networks:
      - sure_net

networks:
  sure_net:
    driver: bridge

```

</details>Then finally you can set your environment variables in the .env file, for the postgres and email details. Just make sure you create again a nice secret key with the command

```
openssl rand -hex 64
```

and then paste it into the .env file for the SECRET\_KEY\_BASE

<details id="bkmrk-.env-postgres_user%3Du"><summary>.env</summary>

```
POSTGRES_USER=usernamedifficult
POSTGRES_PASSWORD=0394jgoipjeroigjoisdjgkljyourcode
POSTGRES_DB=sure_production
SECRET_KEY_BASE=a7523c3d0ae56415046ad8abae168d71074a79534a7062258f8d1d51ac2f76d3c3bc86d86b6b0b307df30d9a6a90a2066a3fa9e67c5e6f374dbd7dd4e0778e13
PORT=3000
SMTP_ADDRESS=smtp.example.com
SMTP_PORT=587
SMTP_DOMAIN=example.com
SMTP_USERNAME=your-username
SMTP_PASSWORD=your-password
SMTP_AUTHENTICATION=plain
SMTP_ENABLE_STARTTLS_AUTO=true
```

</details><p class="callout warning">Note! Make sure that sure has the right writing permissions of 750 for the "sure" folder you are hosting everything in. Otherwise it cannot create a directory for your account.</p>

Most likely you will get an error for because of sure not being able to write to the sure folder. In that case as noted above go into your folder and change the permissions and restart the sure stack.

Then you will be able to reach your sure instance at DOCKERVMIP:Port and create a user account. Now, as with any application you should give it a domain name public or not. If you don't know how to do this check the Reverse Proxy section.

Perfect! Now on the next pages we will discuss some basic settings and things you can do with it. However, just check the [documentation](https://docs.sure.am/) for everything of course.

# 1.5.23 Open Notebook

Open Notebook is the cognitive partner you always wanted and could never explain why. It combines the power of AI with unwavering privacy controls. It's designed for researchers, students, and professionals who want to enhance their learning and abilities while maintaining complete control over workflows, models, and how their data gets used and exposed.

# 1. Installation

We will again use our Dockervm to deploy this application via docker. The installation instructions can be found on their [Github](https://github.com/lfnovo/open-notebook) page but here is the compose file regardless ;)

<details id="bkmrk-compose.yml-services"><summary>compose.yml</summary>

```yaml
services:
  surrealdb:
    image: surrealdb/surrealdb:v2
    # Credentials default to root:root for a zero-config local setup. Before
    # exposing this instance to a network, set SURREAL_USER / SURREAL_PASSWORD
    # in a .env file (see .env.example) — they are applied here and to the
    # open_notebook service below, so the two always stay in sync.
    command: start --log info --user ${SURREAL_USER:-root} --pass ${SURREAL_PASSWORD:-root} rocksdb:/mydata/mydatabase.db
    user: root  # Required for bind mounts on Linux
    ports:
      - "8000:8000"
    volumes:
      - ./surreal_data:/mydata
    environment:
      - SURREAL_EXPERIMENTAL_GRAPHQL=true
    restart: always
    pull_policy: always

  open_notebook:
    image: lfnovo/open_notebook:v1-latest
    ports:
      - "8502:8502"  # Web UI
      - "5055:5055"  # REST API
    environment:
      # REQUIRED: Change this to your own secret string
      # This encrypts your API keys in the database
      - OPEN_NOTEBOOK_ENCRYPTION_KEY=change-me-to-a-secret-string

      # Database connection. SURREAL_USER / SURREAL_PASSWORD default to root:root
      # for local use; override them in a .env file before exposing the instance
      # (the same values configure the surrealdb service above).
      - SURREAL_URL=ws://surrealdb:8000/rpc
      - SURREAL_USER=${SURREAL_USER:-root}
      - SURREAL_PASSWORD=${SURREAL_PASSWORD:-root}
      - SURREAL_NAMESPACE=open_notebook
      - SURREAL_DATABASE=open_notebook
      - API_URL=http://localhost:5055
      - OPEN_NOTEBOOK_PASSWORD=${OPEN_NOTEBOOK_PASSWORD:-secure-webgui-password}
    volumes:
      - ./notebook_data:/app/data
    depends_on:
      - surrealdb
    restart: always
    pull_policy: always
```

</details>Just copy and paste this in your dockhand instance as a new stack. Just makes sure you change the SURREAL\_USER, SURREAL\_PASSWORD and the OPEN\_NOTEBOOK\_PASSWORD to something more complicated than root and root. You can do this in the environment variables section in the Dockhand Stack

Then just deploy the stack and visit it at [http://IP-DOCKERVM:8052](http://localhost:8052)

**Attach Domain Name**

Now, if you want to attach a domain name to your open notebook instance then you need to make a tiny addition to your docker compose file environment variables. Namely the API URL needs to match your domain name. If for instance your URL is opennotebook.example.org then the add the following line to the environment variables of the opennotebook container.

<p class="callout info"> - API\_URL=https://opennotebook.example.org</p>

# 2. Configuration

# 1.5.24 Dawarich

**Dawarich**<span> is a self-hostable web app designed to replace Google Timeline (aka Google Location History). It enables you to:</span>

- Track your location history.
- Visualize your data on an interactive map.
- Create trips and analyze your travel history.
- Share your location with family members.
- Integrate with photo management apps like Immich and Photoprism to visualize geotagged photos.
- Import your location history from Google Maps Timeline, OwnTracks, GPX, GeoJSON and some other sources
- Explore statistics like the number of countries and cities visited, total distance traveled, and more!
- Share your location with family members.

# Owntracks/Traccar clients

[https://tracks.rfeyn.org/api/v1/owntracks/points?api\_key=18349285cbc1dcb8e68427175509225e3a244c9c6791f7bc8a9affe887f46f5f](https://tracks.rfeyn.org/api/v1/owntracks/points?api_key=18349285cbc1dcb8e68427175509225e3a244c9c6791f7bc8a9affe887f46f5f)

Sadly enough they all require google play services to work

# 1. Installation

This app is again extremely simple to install.

<p class="callout warning">What is important is that you set the IP of your DockerVM and the domain name you want to use to access the Dawarich instance in the APPLICATION\_HOSTS= environment variable. Otherwise you won't be able to connect to it from any other machine then local host ! </p>

# 1.5.25 Ente Photos

# 1. Ente vs Immich

<section class="keyvisual" id="bkmrk-ente-vs.-immich-%E2%80%93-a-"># Ente vs. Immich – a comparison

<div class="layout-boundary"><div class="entry-meta"><span class="posted-on">Posted on [<time class="entry-date published updated" datetime="2025-06-16T16:30:00+02:00">June 16, 2025, 16:30</time>](https://kittmedia.com/en/2025/ente-vs-immich-a-comparison/)</span></div></div></section><div class="layout-boundary" id="bkmrk-both-ente-and-immich"><div class="content-area" id="bkmrk-both-ente-and-immich-1"><main class="site-main" id="bkmrk-both-ente-and-immich-2"><article class="post-418 post type-post status-publish format-standard hentry category-software tag-ente tag-immich tag-photo tag-self-hosting tag-unplug-trump" id="bkmrk-both-ente-and-immich-3"><header class="entry-header"></header>Both Ente and Immich are tools to manage images and videos, and both come with a self-hosting option. And even though they do the same thing in general, there are some fundamental differences in their implementation.

<div class="entry-content"><span id="bkmrk-"></span></div>In this article, I explicitly compare them for self-hosting purposes and thus ignoring the cloud version of Ente explicitly. If you don’t want to self-host, Ente would be your way to go anyways.

## Principles

Immich stores the files in is unencrypted form, making them still usable if the software itself breaks. Ente, on the other hand, encrypts all files. While this is generally a good thing, it makes you dependent on their implementation. And if the software breaks, it’s not that easy to get to the files. While in my case I only self-host locally, there’s no special need for an encryption for me.

Aside of that, Immich just stores the files in a directory you want it to, while Ente requires an actual S3 storage, which requires more administrative work.

This is also not a fully review between all functions of both systems. I just write about things I noticed while using them. It’s more an impression on how they behave.

## Installation

Installing Immich is pretty straight forward and doesn’t really left any questions open. This is not the case for Ente and you need to understand how the particular parts of the system work together to get the system working. This is especially true for my TrueNAS Community system in this case, since Immich can be installed via a pre-defined app, while [Ente needs to be installed manually](https://kittmedia.com/en/2025/install-ente-io-on-truenas-community/).

## Import

Since I wanted to import *all* of my photos and videos, both systems had something to do, as there are over 16.000 files to import. Immich tells me when files are excluded, but doesn’t tell me why. I assume it was because of duplicates by importing them via both on iOS and macOS.

None of the apps did it very smoothly, though. While the upload to Ente was way more faster, it also draw so much power and used so much compute resources that the iPhone was nearly unusable during this time. On macOS, it also used around 60 % CPU usage while importing.

Also, the iOS app stopped multiple times and finally crashed, often after 50 – 150 files. But sometimes, it also successfully uploaded more than 1.000 files in one try.

While not requiring that much resources in the Immich app, the upload was way slower. And it too crashed more often than it should.

In the end, in Ente it took me around 4 hours to import all the data, while Immich took me more than 24 hours.

## Mobile iOS app

In short: The Ente app is superior most of the time. Syncing files in the background is faster, viewing items stored on my NAS is way faster, especially noticeable in the same Wi-Fi, where Immich sometimes behaves like it had just a slow 3G connection.

One nice thing I noticed in the Ente app (and made me worried at first, because I didn’t expect it) is that it uses the images on the device itself to display, at least if it has no connection to the server. Thus, images in the Photos app are always displayed there, even without internet connection. Immich, on the other hand, does only store thumbnails locally and doesn’t access locally stored images if there is no connection.

I also like the UI more for Ente, but essentially they are similar. Scrolling is more snappy for the Ente app, while especially faster scrolling is stuttering in the Immich app.

However, this all comes with one major drawback: Nearly everything you do in the Ente app requires very much compute resources, which is noticeable especially when viewing videos. My iPhone 13 Pro gets very hot while watching, while there’s no such problem in Immich.

My best guess is that this is to the continuous encryption and decryption operations in Ente, since the server apps always run very cool and without many resources.

## Server resources

Which brings us to the server resources. Ente can run even with very small amount of resources. According to the documentation, also some embedded devices are sufficient to run it. On the other hand, Immich requires 4 GiB of RAM (recommended 6 GiB) and 2 CPU cores (4 cores recommended).

In my system, the Ente apps need around 130 – 150 MiB RAM and nearly no CPU usage while viewing a video, the S3 storage 300 – 500 MiB RAM and 1 – 3 % CPU usage. Immich uses more than 900 MiB RAM with 5 – 12 % CPU usage while viewing a video.

Immich on the other hand needs around 950 MiB RAM and also 3 % CPU usage while viewing a video.

However, if you upload files, you can see the difference between on-device handling for Ente, which does produce nearly no notable usage on the server, while Immich ramps up to using around 25 % of my AMD Ryzen 5 PRO 2400GE CPU and peaks at 1,6 GiB RAM usage.

And even though all systems are in the same Wi-Fi, a 4K clip sometimes cannot be viewed without buffering on Immich. It just doesn’t load fast enough (this seems to be improved the last weeks through updates, though). However, the comparison is not really fair, since Ente doesn’t allow you to view the raw footage as originally stored. In my case, the original video was around 145 MiB in size, while the video viewed directly in Ente was only half its size. So, there’s definitely some kind of converting taking place in Ente.

Interestingly, Immich has a file storage usage of 127 GiB, while the S3 storage of Ente consumes only 107 GiB. And in its UI, Immich tells me it stores 236 GiB.

## Machine learning

Both projects use machine learning, e.g. for face recognition or searching for natural language and it works fine for both. They also get both a plus for using the correct term machine learning instead of “AI”.

Also, in Ente, machine learning is an on-device process, while Immich does it on server-side. While both should be working fine, in general, I like it more to have it on server-side (since I also own the server) to keep resource usage low on the (often mobile) device.

</article></main></div></div>

# 1.5.26 Immich

# 1. Installation

han

You want to use the immich release version s.t it will always update to the newest version and keep immich up to date.

##### **100MB File size Cloudflare Tunnel Limits**

Source: [Cloudflare Tunnels](https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/)

If you use cloudflare tunnels for your public websites then it is limited to files of 100MB or less. This is a problem of course since lots of video files are larger than 100 MB. Hence, if you use cloudlfare tunnels the files either need to be uploaded in chuncks smaller than a 100MB or you need to remove the cloudflare tunnel and expose your public IP to the internet. The former is of course the best option which can be solved by using

# 30 Journiv

# 1. Installation

Source: [https://www.journiv.com/docs/installation/docker](https://www.journiv.com/docs/installation/docker)

Then go into your terminal and make sure you provide the following permissions for the journiv data folder.

mkdir -p data/app data/postgres data/valkey  
sudo chown -R 1000:1000 data  
sudo chmod -R 755 data

Then fill in the docker compose file

Then copy paste the .env file

Then in the .env file you should create again some secrets with

  
docker compose up -d

Then make sure you have your reverse proxy ready !! Because it will only load for the Domain you have set in the .env file!!

# 31. Tinycld

# 1. Installtion

<div class="log-line" id="bkmrk-"></div><div class="log-line" id="bkmrk--1"></div><div class="log-line" id="bkmrk-first-run-setup%2C-vis">First run setup, visit below URL to configure tinycld: │</div><div class="log-line" id="bkmrk-2026-07-08t00%3A45%3A55."><span class="log-ts">2026-07-08T00:45:55.850609771Z</span> <span class="log-cname">\[tinycld\]</span> │ │</div><div class="log-line" id="bkmrk-2026-07-08t00%3A45%3A55.-1"><span class="log-ts">2026-07-08T00:45:55.850612081Z</span> <span class="log-cname">\[tinycld\]</span> │ [http://0.0.0.0:7090/admin?token=f6a1f9128b179c8d4ac119982b156676c58f893934e170c9a2838171a96748e8](http://0.0.0.0:7090/admin?token=f6a1f9128b179c8d4ac119982b156676c58f893934e170c9a2838171a96748e8)</div><div class="log-line" id="bkmrk--2"></div><div class="log-line" id="bkmrk--3"></div>

# 31. Journal/Diary Applications

This chapter looks at different open source journal/diary applications. As usual we look both at E2EE and non E2EE versions. These applications are meant to provide you with an oversight of your thoughts, the things you did during the day, how you felt, etcetera. Also there will be apps that are local only i.e just work on your phone for instance or once that work via your server that can be accessed on multiple devices and used by multiple users. In this case it is especially necessary that your data is E2EE, since you don't want someone else reading your most personal notes. However, if you host your own server at home then you can go with some beautiful journal applications that are not E2EE.

At this moment the only E2EE encrypted open source diary apps would be Notesnook and Joplin ;) However, I would say they are more focused on being a note taking app with folders, sub folders for studying and developing. So far the best project in my opinion is Journiv that would be most focused on your personal life/diary format, but unfortunately it is not E2EE at this moment. However, if you are self hosting this obviously does not matter ;)

# 1. Memos

The first application that we will discuss is the Memos application

# 2. Journiv

Community: [Discord](https://discord.com/invite/CuEJ8qft46)

At this moment I use Journiv as my main diary application for my personal life. The reason I use this one is the following

1. It allows me to create multiple Journals for different things. For instance a journal for Sports, Work, Relationships, Health, etcetera.
2. Second it allows me to create tags. With these tags I can easily navigate how often I did or had something. For instance how often you went to the gym, had an anxiety attack, how often you took vitamine pills etcetera.
3. It is a new kid on the block with lots of features planned
4. It integrates with Immich, but will integrate with many other features according to their roadmap
5. The only down side to it is that you won't get all the features unless you get a paid subscription. The price is not that high, but it always makes you wonder to what extend the open source app will become a commercial product and just uses open source to sell. However, this could also change over the years of course. At this moment the free version gives you enough capabilities.
6. It allows you to add people to your memories as well. Hence, you can also easily click on a person in your diary and see all the notes that included these people.

# 3. Daily You

# 32. Dashboards

<span>This chapter discusses different open source webbrowser dashboards. You could see it as the landing page of your webbrowser from which you move to your apps or the web. These dashboards are more than just a clickable link, since there are also API integrations possible. </span>

# 1. Homarr

# 5. Dashboards

# 6. Collaboration

This Chapter discusses some collaboration applications i.e alternatives to slack for instance.

# 1. Mattermost

Source: [Mattermost Docker Installation](https://docs.mattermost.com/deployment-guide/server/containers/install-docker.html)

<details id="bkmrk-compose.yml-%23-https%3A"><summary>compose.yml</summary>

```yaml
# https://docs.docker.com/compose/environment-variables/
services:
  postgres:
    image: postgres:${POSTGRES_IMAGE_TAG}
    restart: ${RESTART_POLICY}
    security_opt:
      - no-new-privileges:true
    # See https://docs.mattermost.com/administration-guide/scale/scaling-for-enterprise.html
    # for guidance on memory limits based on your deployment size.
    mem_limit: 16G
    read_only: true
    tmpfs:
      - /tmp
      - /var/run/postgresql
    volumes:
      - ${POSTGRES_DATA_PATH}:/var/lib/postgresql
    environment:
      # timezone inside container
      - TZ

      # necessary Postgres options/variables
      - POSTGRES_USER
      - POSTGRES_PASSWORD
      - POSTGRES_DB

  mattermost:
    depends_on:
      - postgres
    image: mattermost/${MATTERMOST_IMAGE}:${MATTERMOST_IMAGE_TAG}
    restart: ${RESTART_POLICY}
    security_opt:
      - no-new-privileges:true
    # See https://docs.mattermost.com/administration-guide/scale/scaling-for-enterprise.html
    # for guidance on memory limits based on your deployment size.
    mem_limit: 4G
    read_only: ${MATTERMOST_CONTAINER_READONLY}
    tmpfs:
      - /tmp
    volumes:
      - ${MATTERMOST_CONFIG_PATH}:/mattermost/config:rw
      - ${MATTERMOST_DATA_PATH}:/mattermost/data:rw
      - ${MATTERMOST_LOGS_PATH}:/mattermost/logs:rw
      - ${MATTERMOST_PLUGINS_PATH}:/mattermost/plugins:rw
      - ${MATTERMOST_CLIENT_PLUGINS_PATH}:/mattermost/client/plugins:rw
      - ${MATTERMOST_BLEVE_INDEXES_PATH}:/mattermost/bleve-indexes:rw
      # When you want to use SSO with GitLab, you have to add the cert pki chain of GitLab inside Alpine
      # to avoid Token request failed: certificate signed by unknown authority 
      # (link: https://github.com/mattermost/mattermost-server/issues/13059 and https://github.com/mattermost/docker/issues/34)
      # - ${GITLAB_PKI_CHAIN_PATH}:/etc/ssl/certs/pki_chain.pem:ro
    environment:
      # timezone inside container
      - TZ

      # necessary Mattermost options/variables (see env.example)
      - MM_SQLSETTINGS_DRIVERNAME
      - MM_SQLSETTINGS_DATASOURCE

      # necessary for bleve
      - MM_BLEVESETTINGS_INDEXDIR

      # additional settings
      - MM_SERVICESETTINGS_SITEURL
```

</details>Check the permissions of the folders! needs to be 2000:2000

<details id="bkmrk-.env-%C2%A0"><summary>.env</summary>

```
# Domain of service
DOMAIN=mattermost.rfeyn.org

# Container settings
## Timezone inside the containers. The value needs to be in the form 'Europe/Berlin'.
## A list of these tz database names can be looked up at Wikipedia
## https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
TZ=Europe/Amsterdam
RESTART_POLICY=unless-stopped

# Postgres settings
## Documentation for this image and available settings can be found on hub.docker.com
## https://hub.docker.com/_/postgres
## Please keep in mind this will create a superuser and it's recommended to use a less privileged
## user to connect to the database.
## A guide on how to change the database user to a nonsuperuser can be found in docs/creation-of-nonsuperuser.md
POSTGRES_IMAGE_TAG=18-alpine
POSTGRES_DATA_PATH=./volumes/db/var/lib/postgresql/data

POSTGRES_USER=mmuser
POSTGRES_PASSWORD=aosdjfasjdfajsfjlaskdfasdf
POSTGRES_DB=mattermost

# Nginx
## The nginx container will use a configuration found at the NGINX_MATTERMOST_CONFIG. The config aims
## to be secure and uses a catch-all server vhost which will work out-of-the-box. For additional settings
## or changes ones can edit it or provide another config. Important note: inside the container, nginx sources
## every config file inside */etc/nginx/conf.d* ending with a *.conf* file extension.

## Inside the container the uid and gid is 101. The folder owner can be set with
## `sudo chown -R 101:101 ./nginx` if needed.
## Note that this repository requires nginx version 1.25.1 or later
NGINX_IMAGE_TAG=alpine

## The folder containing server blocks and any additional config to nginx.conf
NGINX_CONFIG_PATH=./nginx/conf.d
NGINX_DHPARAMS_FILE=./nginx/dhparams4096.pem

CERT_PATH=./volumes/web/cert/cert.pem
KEY_PATH=./volumes/web/cert/key-no-password.pem
#GITLAB_PKI_CHAIN_PATH=<path_to_your_gitlab_pki>/pki_chain.pem
#CERT_PATH=./certs/etc/letsencrypt/live/${DOMAIN}/fullchain.pem
#KEY_PATH=./certs/etc/letsencrypt/live/${DOMAIN}/privkey.pem

## Exposed ports to the host. Inside the container 80, 443 and 8443 will be used
HTTPS_PORT=443
HTTP_PORT=80
CALLS_PORT=8443

# Mattermost settings
## Inside the container the uid and gid is 2000. The folder owner can be set with
## `sudo chown -R 2000:2000 ./volumes/app/mattermost`.
MATTERMOST_CONFIG_PATH=./volumes/app/mattermost/config
MATTERMOST_DATA_PATH=./volumes/app/mattermost/data
MATTERMOST_LOGS_PATH=./volumes/app/mattermost/logs
MATTERMOST_PLUGINS_PATH=./volumes/app/mattermost/plugins
MATTERMOST_CLIENT_PLUGINS_PATH=./volumes/app/mattermost/client/plugins
MATTERMOST_BLEVE_INDEXES_PATH=./volumes/app/mattermost/bleve-indexes

## Bleve index (inside the container)
MM_BLEVESETTINGS_INDEXDIR=/mattermost/bleve-indexes

## This will be 'mattermost-enterprise-edition' or 'mattermost-team-edition' based on the version of Mattermost you're installing.
MATTERMOST_IMAGE=mattermost-enterprise-edition
## Update the image tag if you want to upgrade your Mattermost version. You may also upgrade to the latest one. The example is based on the latest Mattermost ESR versi>
MATTERMOST_IMAGE_TAG=11.7.0

## Make Mattermost container readonly. This interferes with the regeneration of root.html inside the container. Only use
## it if you know what you're doing.
## See https://github.com/mattermost/docker/issues/18
MATTERMOST_CONTAINER_READONLY=false

## The app port is only relevant for using Mattermost without the nginx container as reverse proxy. This is not meant
## to be used with the internal HTTP server exposed but rather in case one wants to host several services on one host
## or for using it behind another existing reverse proxy.
APP_PORT=1023

## Configuration settings for Mattermost. Documentation on the variables and the settings itself can be found at
## https://docs.mattermost.com/administration/config-settings.html
## Keep in mind that variables set here will take precedence over the same setting in config.json. This includes
## the system console as well and settings set with env variables will be greyed out.

## Below one can find necessary settings to spin up the Mattermost container
MM_SQLSETTINGS_DRIVERNAME=postgres
MM_SQLSETTINGS_DATASOURCE=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?sslmode=disable&connect_timeout=10

## Example settings (any additional setting added here also needs to be introduced in the docker-compose.yml)
```

</details>Notifications: [https://docs.mattermost.com/end-user-guide/preferences/manage-your-mobile-notifications.html](https://docs.mattermost.com/end-user-guide/preferences/manage-your-mobile-notifications.html)

# 2. Matrix

# 4. LLM Dashboards

This chapter contains different open source LLM access dashboards. Hopefully, it will include also open source LLM's whenever they come out. Yes OpenAI is not open source. Up untill then it mainly discusses open source dashboard where you can add your own models and store all the gathered data locally as well.

# 1. OpenWebui

#### Installation

There are different ways you can install [OpenWebUI](https://docs.openwebui.com/getting-started/quick-start/) but as usual I like to install it with docker compose that also includes Ollama as well. You can find the docker compose file over [here](services:%20%20%20ollama:%20%20%20%20%20volumes:%20%20%20%20%20%20%20-%20ollama:/root/.ollama%20%20%20%20%20container_name:%20ollama%20%20%20%20%20pull_policy:%20always%20%20%20%20%20tty:%20true%20%20%20%20%20restart:%20unless-stopped%20%20%20%20%20image:%20ollama/ollama:${OLLAMA_DOCKER_TAG-latest}%20%20%20%20open-webui:%20%20%20%20%20build:%20%20%20%20%20%20%20context:%20.%20%20%20%20%20%20%20dockerfile:%20Dockerfile%20%20%20%20%20image:%20ghcr.io/open-webui/open-webui:${WEBUI_DOCKER_TAG-main}%20%20%20%20%20container_name:%20open-webui%20%20%20%20%20volumes:%20%20%20%20%20%20%20-%20open-webui:/app/backend/data%20%20%20%20%20depends_on:%20%20%20%20%20%20%20-%20ollama%20%20%20%20%20ports:%20%20%20%20%20%20%20-%20${OPEN_WEBUI_PORT-3000}:8080%20%20%20%20%20environment:%20%20%20%20%20%20%20-%20'OLLAMA_BASE_URL=http://ollama:11434'%20%20%20%20%20%20%20-%20'WEBUI_SECRET_KEY='%20%20%20%20%20extra_hosts:%20%20%20%20%20%20%20-%20host.docker.internal:host-gateway%20%20%20%20%20restart:%20unless-stopped%20%20volumes:%20%20%20ollama:%20{}%20%20%20open-webui:%20{})

<details id="bkmrk-compose.yml-services"><summary>compose.yml</summary>

```
services:
  ollama:
    volumes:
      - ./ollama:/root/.ollama
    container_name: ollama
    environment:
      - OLLAMA_NUM_GPU=1     
      - GPU_DEVICE_ORDINAL=0
    devices:    
      - /dev/dri/renderD128:/dev/dri/renderD128
    pull_policy: always
    tty: true
    restart: unless-stopped
    image: ollama/ollama:${OLLAMA_DOCKER_TAG-latest}

  open-webui:
    build:
      context: .
      dockerfile: Dockerfile
    image: ghcr.io/open-webui/open-webui:${WEBUI_DOCKER_TAG-main}
    container_name: open-webui
    volumes:
      - ./open-webui:/app/backend/data
    depends_on:
      - ollama
    ports:
      - ${OPEN_WEBUI_PORT-3000}:8080
    environment:
      - 'OLLAMA_BASE_URL=http://ollama:11434'
      - 'WEBUI_SECRET_KEY='
    extra_hosts:
      - host.docker.internal:host-gateway
    restart: unless-stopped


```

</details>and the environment variables fil

<details id="bkmrk-.env-%23-ollama-url-fo"><summary>.env</summary>

```
# Ollama URL for the backend to connect
# The path '/ollama' will be redirected to the specified backend URL
OLLAMA_BASE_URL='http://localhost:11434'

OPENAI_API_BASE_URL=''
OPENAI_API_KEY=''

# AUTOMATIC1111_BASE_URL="http://localhost:7860"

# For production, you should only need one host as
# fastapi serves the svelte-kit built frontend and backend from the same host and port.
# To test # Ollama URL for the backend to connect
# The path '/ollama' will be redirected to the specified backend URL
OLLAMA_BASE_URL='http://localhost:11434'

OPENAI_API_BASE_URL=''
OPENAI_API_KEY=''
OPEN_WEBUI_PORT=1024

# AUTOMATIC1111_BASE_URL="http://localhost:7860"

# For production, you should only need one host as
# fastapi serves the svelte-kit built frontend and backend from the same host and port.
# To test with CORS locally, you can set something like
# CORS_ALLOW_ORIGIN='http://localhost:5173;http://localhost:8080'
CORS_ALLOW_ORIGIN='*'

# Set to false to keep memory tools enabled without adding memory context to the system context.
ENABLE_MEMORY_SYSTEM_CONTEXT=true

# For production you should set this to match the proxy configuration (127.0.0.1)
FORWARDED_ALLOW_IPS='*'

# DO NOT TRACK
SCARF_NO_ANALYTICS=true
DO_NOT_TRACK=true
ANONYMIZED_TELEMETRY=false

# Valkey Vector Store (requires VECTOR_DB=valkey)
# VALKEY_URL='valkey://localhost:6379'
# VALKEY_COLLECTION_PREFIX='open_webui'
# VALKEY_INDEX_TYPE='HNSW'
# VALKEY_DISTANCE_METRIC='COSINE'
# VALKEY_HNSW_M='16'
# VALKEY_HNSW_EF_CONSTRUCTION='200'
# VALKEY_HNSW_EF_RUNTIME='10'with CORS locally, you can set something like
# CORS_ALLOW_ORIGIN='http://localhost:5173;http://localhost:8080'
CORS_ALLOW_ORIGIN='*'

# Set to false to keep memory tools enabled without adding memory context to the system context.
ENABLE_MEMORY_SYSTEM_CONTEXT=true

```

</details>Then simply deploy the stack with docker compose up -d or with Dockhand by simply clicking on Deploy stack ;) !! Then if it is all green lights you will be able to access it either on the URL you sepcified in the .env file or on http://DOCKERVM-IP:PORT. You will then be presented with this interesting screen ;)

[![Screenshot From 2026-07-16 16-02-49.png](https://docs.rfeyn.org/uploads/images/gallery/2026-07/scaled-1680-/foOqzhCKeN30U2TO-screenshot-from-2026-07-16-16-02-49.png)](https://docs.rfeyn.org/uploads/images/gallery/2026-07/foOqzhCKeN30U2TO-screenshot-from-2026-07-16-16-02-49.png)

Then simply create your admin account and save it in your Vaultwarden account. You will then be brought to your OpenWebUI dashboard. Note! There is no model configured yet, so that's what we will do in the next step.

[![Screenshot From 2026-07-16 16-16-48.png](https://docs.rfeyn.org/uploads/images/gallery/2026-07/scaled-1680-/Kr6naGifXRsks5kk-screenshot-from-2026-07-16-16-16-48.png)](https://docs.rfeyn.org/uploads/images/gallery/2026-07/Kr6naGifXRsks5kk-screenshot-from-2026-07-16-16-16-48.png)

# 1. Cloud Storage

<span>This book describes different cloud storage experience </span>

# 20. Documentation

# 1. HedgeDocs

Source: [https://docs.hedgedoc.dev/how-to/reverse-proxy/](https://docs.hedgedoc.dev/how-to/reverse-proxy/)

# 8. ToDo Software

<span>This chapter discusses different ToDo list open source software. This can either be integrated into another bigger application or completely stand alone. </span>

# 1. Vikunja

Source: [Vikunja](https://vikunja.io/install/)

# 10. Nextcloud ToDo

Nextcloud ToDo comes integrated with Nextcloud as an application.

# Messenger Applications

# 1. Session Messenger

<span class="font-semibold" data-streamdown="strong"><span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">Source: [Session Messenger FAQ](https://getsession.org/faq)</span></span>

<span class="font-semibold" data-streamdown="strong"><span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">Source: [Arguments against Session Messenger](https://www.youtube.com/watch?v=BIZul-40s3E)</span></span>

<span class="font-semibold" data-streamdown="strong"><span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">Loki: Is basiscally Tor for rich people</span></span>

<span class="font-semibold" data-streamdown="strong"><span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">Session</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">Messenger</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">would</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">not</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">go</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">down</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">if</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">seed</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">nodes</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">were</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">destroyed</span></span><span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">,</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">though</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">it</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">would</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">create</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">temporary</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">disruptions</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">for</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">new</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">users</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">trying</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">to</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">connect.</span>

<span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">Here's</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">how</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">it</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">would</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">work:</span>

<span class="font-semibold" data-streamdown="strong"><span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">Initial</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">impact</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">on</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">new</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">users:</span></span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">Seed</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">nodes</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">are</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">bootstrap</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">points</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">that</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">help</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">new</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">users</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">find</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">and</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">connect</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">to</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">the</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">decentralized</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">network.</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">If</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">all</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">seed</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">nodes</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">were</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">destroyed,</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">new</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">users</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">would</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">have</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">difficulty</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">joining</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">the</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">network</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">initially</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">since</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">they</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">wouldn't</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">have</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">a</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">starting</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">point</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">to</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">discover</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">peers.</span>

<span class="font-semibold" data-streamdown="strong"><span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">Existing</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">users</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">unaffected:</span></span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">Users</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">already</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">connected</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">to</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">the</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">network</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">would</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">continue</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">to</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">function</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">normally.</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">Their</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">clients</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">maintain</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">direct</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">peer-to-peer</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">connections</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">with</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">other</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">users</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">and</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">nodes,</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">so</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">they</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">wouldn't</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">depend</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">on</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">seed</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">nodes</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">to</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">keep</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">messaging.</span>

<span class="font-semibold" data-streamdown="strong"><span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">Recovery</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">and</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">resilience:</span></span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">The</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">decentralized</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">nature</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">of</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">Session</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">Messenger</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">means</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">that:</span>

<div class="ucB71mHYvyHsWKjYfYKI" id="bkmrk-new-seed-nodes-could"><div class="DDjJOsxcW6f8fPcDWaJx"><div class="JrWQJZIYGnawLoKSzZsO"><div class="" data-dark-theme=""><div class="space-y-4 whitespace-normal *:first:mt-0 *:last:mb-0 VrBPSncUavA1d7C9kAc5 U_5uJaZtJAYAFWUmk7aU">- <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">New</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">seed</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">nodes</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">could</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">be</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">deployed</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">relatively</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">quickly</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">by</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">the</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">community</span>
- <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">Users</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">could</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">potentially</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">connect</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">manually</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">by</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">knowing</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">the</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">address</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">of</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">at</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">least</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">one</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">existing</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">peer</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">on</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">the</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">network</span>
- <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">The</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">network's</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">distributed</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">architecture</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">is</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">specifically</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">designed</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">to</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">be</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">resistant</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">to</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">this</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">kind</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">of</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">centralized</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">attack</span>

</div></div></div></div></div><span class="font-semibold" data-streamdown="strong"><span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">The</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">key</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 250ms; --sd-easing: ease-in;">distinction:</span></span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">Session's</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">design</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">acknowledges</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">that</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">some</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">bootstrap</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">infrastructure</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">is</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">necessary,</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">but</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">the</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">actual</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">message</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">routing</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">and</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">peer-to-peer</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">communication</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">happens</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">across</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">the</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">distributed</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">network.</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">Destroying</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">seed</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">nodes</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">would</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">be</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">more</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">of</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">an</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">inconvenience</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">than</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">a</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">fatal</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">blow—it</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">would</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">slow</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">adoption</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">and</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">create</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">friction</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">for</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">newcomers,</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">but</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">wouldn't</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">collapse</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">the</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">network</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">for</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">active</span> <span data-sd-animate="true" style="--sd-animation: sd-fadeIn; --sd-duration: 0ms; --sd-easing: ease-in;">participants.</span>

This is actually one of the arguments proponents make for decentralized messenger systems: they're theoretically more resilient to government or corporate infrastructure takedowns compared to services relying on centralized data centers.