diff --git a/NUT-Network UPS Tools/readme.md b/NUT-Network UPS Tools/readme.md
new file mode 100644
index 0000000..c56189a
--- /dev/null
+++ b/NUT-Network UPS Tools/readme.md
@@ -0,0 +1,232 @@
+# NUT - Network UPS Tools
+
+###### guide-by-example
+
+![logo](https://i.imgur.com/TAIgm4Y.png)
+
+# Purpose & Overview
+
+UPS - uninterruptible power supply managment. Huge drivers support.
+
+
+* [Official site](https://networkupstools.org/index.html)
+* [Github](https://github.com/networkupstools/nut)
+* [Archlinux Wiki](https://wiki.archlinux.org/title/Network_UPS_Tools)
+
+The main objective is to be able to shutdown properly larger amount of devices
+when power goes out and ups battery starts to get low.
+
+Nut is collection of programs and drivers, mostly written in C.
+For webgui it uses apache webserver.
+
+
+
+
+
+[Techno Tim youtube video](https://www.youtube.com/watch?v=vyBP7wpN72c)
+
+As per the video I am testing this running on rpi.
+[Here's](https://github.com/DoTheEvo/selfhosted-apps-docker/tree/master/arch_raspberry_pi)
+arch on rpi setup.
+
+---
+
+![interface-pic](https://i.imgur.com/ekA7Hms.png)
+
+# Files and directory structure
+
+```
+/home/
+└── ~/
+ └── docker/
+ └── rustdesk/
+ ├── 🗁 rustdesk_data/
+ ├── 🗋 .env
+ └── 🗋 docker-compose.yml
+```
+
+* `rustdesk_data/` - persistent data, contains sqlite database and the keys
+* `.env` - a file containing environment variables for docker compose
+* `docker-compose.yml` - a docker compose file, telling docker how to run the containers
+
+You only need to provide the two files.
+The directory is created by docker compose on the first run.
+
+# docker-compose
+
+Using [S6-overlay](https://github.com/rustdesk/rustdesk-server#s6-overlay-based-images)
+based image.
+It's a simpler, single container approach. The
+[complexity](https://github.com/rustdesk/rustdesk-server#classic-image)
+of rustdesk's `hbbs` server and `hbbr` relay hidden.
+
+No network section since no http traffic that would need reverse proxy, yet.
+So just mapped ports on to docker host to do their thing.
+
+`docker-compose.yml`
+```yml
+services:
+ rustdesk:
+ image: rustdesk/rustdesk-server-s6:1.1.7-1
+ container_name: rustdesk
+ hostname: rustdesk
+ restart: unless-stopped
+ env_file: .env
+ ports:
+ - "21116:21116"
+ - "21115:21115"
+ - "21116:21116/udp"
+ - "21117:21117"
+ - "21118:21118"
+ - "21119:21119"
+ volumes:
+ - ./rustdesk_data:/data
+```
+
+`.env`
+```bash
+# GENERAL
+TZ=Europe/Bratislava
+
+# RUSTDESK
+RELAY=rust.example.com:21117
+ENCRYPTED_ONLY=1
+# KEY_PRIV=
+# KEY_PUB=
+```
+
+In the `.env` file encryption is enabled, so that only clients that have
+correct public key will be allowed access to the rustdesk server.
+The keys are generated on the first run of the compose and can be found in
+the `rustdesk_data` directory.
+Once generated they should be added to the `.env` file for easier migration.
+The public key needs to be distributed with the clients apps installation.
+
+# Port forwarding
+
+as can be seen in the compose
+
+* **21115 - 21119** TCP need to be forwarded to docker host
+* **21116** is TCP **and UDP**
+
+21115 is used for the NAT type test,
+21116/UDP is used for the ID registration and heartbeat service,
+21116/TCP is used for TCP hole punching and connection service,
+21117 is used for the Relay services,
+and 21118 and 21119 are used to support web clients.
+[source](https://rustdesk.com/docs/en/self-host/install/)
+
+---
+
+![interface-pic](https://i.imgur.com/CK6pRyq.png)
+
+# The installation on clients
+
+* Download and install the client apps from [the official site](https://rustdesk.com/).
+* Three dots > ID/Relay Server
+ * `ID Server`: rust.example.com
+ * `Key`: *\*
+* The green dot at the bottom should be green saying "ready".
+
+![settings-pic](https://i.imgur.com/lX6egMH.png)
+
+**On windows** one
+[can deploy](https://rustdesk.com/docs/en/self-host/install/#put-config-in-rustdeskexe-file-name-windows-only)
+client with **pre-sets** by renaming the installation file to:
+`rustdesk-host=,key=.exe`
+
+example: `rustdesk-host=rust.example.com,key=3AVva64bn1ea2vsDuOuQH3i8+2M=.exe`
+
+If by chance the public key contains symbols not usable in windows filenames,
+down the container, delete the files `id_ed25519` and `id_ed25519.pub`,
+up the container and try with the new keys.
+
+# Extra info
+
+* You really really **really want to be using domain and not your public IP**
+ when installing clients and setting ID server. That `rust.example.com`
+ can be changed to point at a different IP any time you want. Hard set IP not.
+* Can do `tcpdump -n udp port 21116` on a docker host to **see heartbeat** udp traffic.
+ Seems machines report-in every \~13 seconds.
+* on **windows** a **service** named `rustdesk` is enabled.
+ Disable it if the machine should be accessible only on demand,
+ when someone first runs rustdesk manually.
+ In powershell - `Set-Service rustdesk -StartupType Disabled`
+* One can relatively easily
+ **hardcode server url and pub key in to an executable** using
+ [github actions.](https://rustdesk.com/docs/en/self-host/hardcode-settings/)
+ Tested it and it works. But seems you can only do workflow run of nightly build,
+ meaning all the latest stuff added is included, which means higher chance of bugs.
+ Make sure you do step *"Enable upload permissions for workflows"*,
+ before you run the workflow.
+* Questions about issues with selfhosting are **not answered** on github -
+ [#763](https://github.com/rustdesk/rustdesk/discussions/763),
+ next to try is their [discord](https://discord.com/invite/nDceKgxnkV) or
+ [subreddit](https://www.reddit.com/r/rustdesk/).
+* [FAQ](https://github.com/rustdesk/rustdesk/wiki/FAQ)
+* How does [rustdesk work?](https://github.com/rustdesk/rustdesk/wiki/How-does-RustDesk-work%3F)
+
+![logo](https://i.imgur.com/ptfVMtJ.png)
+
+# Trouble shooting
+
+---
+
+#### If just one machine is having issues.
+
+uninstall, plus delete:
+
+* `C:\Windows\ServiceProfiles\LocalService\AppData\Roaming\RustDesk`
+* `%AppData%\RustDesk`
+
+Restart. Reinstall.
+Do not use the installer you used before, **download** from the site latest.
+
+---
+
+#### Error - Failed to connect to relay server
+
+* I had wrong url set as `RELAY` in the `.env`
+* if url is correct I would test if port 21117 tcp forwards
+
+---
+
+#### Investigate port forwarding
+
+Install netcat and tcpdump on the docker host.
+
+* docker compose down rustdesk container so that ports are free to use
+* start a small netcat server listening on whichever port we test
+ `sudo nc -u -vv -l -p 21116`
+ the `-u` means udp traffic, delete to do tcp
+* on a machine somewhere else in the world, not on the same network, try
+ `nc -u 21116`
+
+If you write something and press enter, it should appear on the other machine, confirming
+that port forwarding works.
+Also useful command can be `tcpdump -n udp port 21116`
+When port forwarding works, one should see heartbeat chatter,
+as machines with installed rustdesk are announcing themselves every \~13 seconds.
+
+---
+
+# Manual image update:
+
+- `docker-compose pull`
+- `docker-compose up -d`
+- `docker image prune`
+
+# Backup and restore
+
+#### Backup
+
+Using [borg](https://github.com/DoTheEvo/selfhosted-apps-docker/tree/master/borg_backup)
+that makes daily snapshot of the entire directory.
+
+#### Restore
+
+* down the bookstack containers `docker-compose down`
+* delete the entire bookstack directory
+* from the backup copy back the bookstack directory
+* start the containers `docker-compose up -d`
+
diff --git a/README.md b/README.md
index 6b8ffbf..a6229a2 100644
--- a/README.md
+++ b/README.md
@@ -49,10 +49,6 @@ Repo documents self hosted apps in similar format and also uses caddy for revers
- `docker-compose.yml` does **not** need any **editing** to get something up,
**changes** are to be done in the `.env` file.
-- **Not using** `ports` directive if theres **only** web traffic for a container.
- Theres an expectation of running a **reverse proxy** which makes **mapping ports**
- to a docker host **unnecessary**. Instead `expose` is used which is basically
- just documentation.
- For **persistent** storage **bind mount** `./whatever_data` is used.
No volumes, nor static path somewhere... just relative path next to compose file.
- **No version** declaration at the beginning of **compose**, as the practice was
@@ -224,28 +220,27 @@ or enable freshly discovered feature for all future deployments.
### For docker noobs
-First, docker is easy. Like really.
+Docker is easy. Really.
-Second, there are two main uses.
+There are two main uses.
-* A developer who daily works on apps and docker eases everything about it,
- from setting up enviroment, to testing and deployment.
-* A hosting approach, where you are not that concerned with detials of what
- and how works in the container that is prepared for you by developers,
- you just want it running
+* For developers who daily work on apps and docker eases everything about it,
+ from setting up environment, to testing and deployment.
+* A hosting approach, where you mostly care about getting containers, that are
+ prepared for you by developers, up and running.
-This whole repo is obviously about the second use. So be careful that you wont
+This repo is about the second use. So be careful that you wont
spend time on resources used to educate developers. Sure, if you get through
-that you will know docker better, but theres always the danger that after sinking
-4 hours learning, one still cant get plain nginx web server up and working
-and loses motivation.
-And my personal preference in learning is getting something up as fast as possible
-and then tinker with it and try to understand how it works.
+that you will know docker better, but theres the danger that after sinking
+4 hours reading and watching videos you still cant get a plain nginx web server
+up and running and loses motivation.
So when googling for guides, look for **docker compose**
-rather than just **docker** tutorials and notice if they are talking some core
-fundamentals or deployment.
+rather than just **docker** tutorials.
+[Beginners speedrun to selfhosting something in docker](beginners-speedrun-selfhosting/)
+
+* [Good stuff](https://adamtheautomator.com/docker-compose-tutorial/)
* [This](https://youtu.be/DM65_JyGxCo) one is pretty good. That entire channel
has good stuff.
diff --git a/audiobookshelf/readme.md b/audiobookshelf/readme.md
new file mode 100644
index 0000000..cb40b5f
--- /dev/null
+++ b/audiobookshelf/readme.md
@@ -0,0 +1,183 @@
+# Audiobookshelf
+
+###### guide-by-example
+
+![logo](https://i.imgur.com/gSyMEvD.png)
+
+# Purpose & Overview
+
+WORK IN PROGRESS
+WORK IN PROGRESS
+WORK IN PROGRESS
+
+Selfhosted audiobook library.
+
+* [Official site](https://www.audiobookshelf.org/)
+* [Github](https://github.com/advplyr/audiobookshelf)
+
+Jellyfin if a free media system, an alternative to proprietary Plex.
+The core server side is written in C#, web client in Javascript,
+and a number of other clients written in various languages and frameworks.
+
+Starting point for me was [this viggy96 repo](https://github.com/viggy96/container_config)
+
+# Files and directory structure
+
+```
+/mnt/
+└── bigdisk/
+ ├── tv/
+ ├── movies/
+ └── music/
+/home/
+└── ~/
+ └── docker/
+ └── jellyfin/
+ ├── jellyfin-cache/
+ ├── jellyfin-config/
+ ├── transcodes/
+ ├── .env
+ └── docker-compose.yml
+```
+
+* `/mnt/bigdisk/...` - a mounted media storage share
+* `jellyfin-cache/` - cache
+* `jellyfin-config/` - configuration
+* `transcodes/` - transcoded video storage
+* `.env` - a file containing environment variables for docker compose
+* `docker-compose.yml` - a docker compose file, telling docker how to run the containers
+
+You only need to provide the two files.
+The directories are created by docker compose on the first run.
+
+# docker-compose
+
+The media are mounted in read only mode.
+
+`docker-compose.yml`
+```yml
+services:
+
+ jellyfin:
+ image: jellyfin/jellyfin:latest
+ container_name: jellyfin
+ hostname: jellyfin
+ restart: unless-stopped
+ env_file: .env
+ devices:
+ - /dev/dri
+ volumes:
+ - ./transcodes/:/transcodes
+ - ./jellyfin-config:/config
+ - ./jellyfin-cache:/cache
+ - /mnt/bigdisk/serialy:/media/video:ro
+ - /mnt/bigdisk/mp3/moje:/media/music:ro
+ ports:
+ - "8096:8096"
+ - "1900:1900/udp"
+
+networks:
+ default:
+ name: $DOCKER_MY_NETWORK
+ external: true
+```
+
+`.env`
+```bash
+# GENERAL
+DOCKER_MY_NETWORK=caddy_net
+TZ=Europe/Bratislava
+```
+
+**All containers must be on the same network**.
+Which is named in the `.env` file.
+If one does not exist yet: `docker network create caddy_net`
+
+# Reverse proxy
+
+Caddy is used, details
+[here](https://github.com/DoTheEvo/selfhosted-apps-docker/tree/master/caddy_v2).
+
+`Caddyfile`
+```
+jellyfin.{$MY_DOMAIN} {
+ reverse_proxy jellyfin:8096
+}
+```
+
+# First run
+
+
+![interface-pic](https://i.imgur.com/pZMi6bb.png)
+
+
+# Specifics of my setup
+
+* no long term use yet
+* amd cpu and no gpu, so no experience with hw transcoding
+* media files are stored and shared on trunas scale VM
+ and mounted directly on the docker host using [systemd mounts](https://forum.manjaro.org/t/root-tip-systemd-mount-unit-samples/1191),
+ instead of fstab or autofs.
+
+ `/etc/systemd/system/mnt-bigdisk.mount`
+ ```ini
+ [Unit]
+ Description=12TB truenas mount
+
+ [Mount]
+ What=//10.0.19.19/Dataset-01
+ Where=/mnt/bigdisk
+ Type=cifs
+ Options=ro,username=ja,password=qq,file_mode=0700,dir_mode=0700,uid=1000
+ DirectoryMode=0700
+
+ [Install]
+ WantedBy=multi-user.target
+ ```
+
+ `/etc/systemd/system/mnt-bigdisk.automount`
+ ```ini
+ [Unit]
+ Description=12TB truenas mount
+
+ [Automount]
+ Where=/mnt/bigdisk
+
+ [Install]
+ WantedBy=multi-user.target
+ ```
+
+ to automount on boot - `sudo systemctl enable mnt-bigdisk.automount`
+
+# Troubleshooting
+
+
+![error-pic](https://i.imgur.com/KQhmZTQ.png)
+
+*We're unable to connect to the selected server right now. Please ensure it is running and try again.*
+
+If you encounter this, try opening the url in browsers private window.
+If it works then clear the cookies in your browser.
+
+
+# Update
+
+Manual image update:
+
+- `docker-compose pull`
+- `docker-compose up -d`
+- `docker image prune`
+
+# Backup and restore
+
+#### Backup
+
+Using [borg](https://github.com/DoTheEvo/selfhosted-apps-docker/tree/master/borg_backup)
+that makes daily snapshot of the entire directory.
+
+#### Restore
+
+* down the bookstack containers `docker-compose down`
+* delete the entire bookstack directory
+* from the backup copy back the bookstack directory
+* start the containers `docker-compose up -d`
diff --git a/beginners-speedrun-selfhosting/readme.md b/beginners-speedrun-selfhosting/readme.md
index 9f92776..40d55bb 100644
--- a/beginners-speedrun-selfhosting/readme.md
+++ b/beginners-speedrun-selfhosting/readme.md
@@ -65,7 +65,7 @@ You know little and want to start somewhere, FAST!
![docker_logo](https://i.imgur.com/6SS5lFj.png)
-Docker - a thing that makes hosting super easy, people prepared *recipies*,
+**Docker** - a thing that makes hosting super easy, people prepared *recipies*,
you copy paste them, maybe edit a bit, run them
* **install docker-compose** - `sudo pacman -S docker-compose`
diff --git a/jellyfin/readme.md b/jellyfin/readme.md
index cb8014d..2d87bb7 100644
--- a/jellyfin/readme.md
+++ b/jellyfin/readme.md
@@ -74,8 +74,8 @@ services:
- /mnt/bigdisk/serialy:/media/video:ro
- /mnt/bigdisk/mp3/moje:/media/music:ro
ports:
- - "1900:1900/udp"
- "8096:8096"
+ - "1900:1900/udp"
networks:
default:
diff --git a/kopia_backup/readme.md b/kopia_backup/readme.md
index f1c2631..5e6d3f5 100644
--- a/kopia_backup/readme.md
+++ b/kopia_backup/readme.md
@@ -206,8 +206,8 @@ WantedBy=multi-user.target
# Kopia in Windows
-While GUI version seems like a way to go.. well its not there yet.
-The schedule it uses is running only under a user, theres no certainty it will run.
+While GUI version seems like a way to go.. its not there yet.
+The way the schedule is running - it uses is running only under a user, theres no certainty it will run.
So here goes cli version
diff --git a/vaultwarden/readme.md b/vaultwarden/readme.md
index 0b68085..eeccf71 100644
--- a/vaultwarden/readme.md
+++ b/vaultwarden/readme.md
@@ -68,9 +68,10 @@ services:
env_file: .env
volumes:
- ./vaultwarden_data/:/data/
+ ports:
+ - "3012:3012"
expose:
- - 80:80
- - 3012:3012
+ - "80"
networks:
default:
diff --git a/zammad/readme.md b/zammad/readme.md
index 2ede383..cf0bdc6 100644
--- a/zammad/readme.md
+++ b/zammad/readme.md
@@ -250,3 +250,9 @@ so in nginx check /opt/zammad and its content with `ls -al`,
if its owned by zammad user.
if its root use `chown -R zammad:zammad /opt/zammad`
and down and up the stack.
+
+-------
+
+# Links
+
+* [Zammad Helpdesk creating duplicate users when using SAML auth](https://www.reddit.com/r/selfhosted/comments/13esjnx/zammad_helpdesk_creating_duplicate_users_when/)