mirror of
https://github.com/alexbelgium/hassio-addons.git
synced 2026-10-10 18:21:36 +02:00
feat(kapowarr): new add-on with Home Assistant ingress support (#2999)
* feat(kapowarr): new add-on with Home Assistant ingress support Kapowarr is a comic book library manager in the *arr family. The add-on is built on the upstream image (mrcas/kapowarr), with the repository's standard nginx ingress scaffolding on top. Ingress uses the pattern komga and bazarr already use here: Kapowarr renders absolute urls from its url base, Home Assistant strips its own ingress prefix before forwarding, so Kapowarr is started with --UrlBase /kapowarr and nginx rewrites that fixed prefix back onto the ingress entry. Database and logs go to the add-on configuration directory. Temporary downloads are symlinked there rather than passed with --TempDownloadFolder, which upstream re-applies on its own restarts and would keep overwriting a folder chosen in Settings > Download. * fix(kapowarr): review fixes from the codex pass - repair a /app/temp_downloads symlink pointing at the wrong target instead of accepting any symlink - exclude logs and temporary downloads from Home Assistant backups: the temp folder now lives in the add-on config directory and can hold gigabytes - fix the /dev/nvme2n3p3 typo inherited from the copied device list (the partition is nvme2n1p3); the same typo is present in the other add-ons - document that the url base must not be changed, and that a non-zero PUID only reaches folders that user can already access - drop three dead Dockerfile lines (BASHIO_VERSION is overridden inside ha_automatic_packages.sh, USER root is a no-op on this image) * fix(kapowarr): pin host and port too, not just the url base Found by a Codex review that could read the upstream source. Kapowarr stores host, port and url base in its database and reads the stored value whenever the matching flag is absent. Only --UrlBase was passed, so a host or port changed in Settings > General survived every restart and upgrade while nginx and the healthcheck stayed pointed at 127.0.0.1:5656 -- a permanent 502 with no way back except editing the database by hand. All three flags are startup-only upstream, so passing them re-applies the add-on's values once per container start without fighting the self-restarts Kapowarr performs after a settings change.
This commit is contained in:
10
kapowarr/CHANGELOG.md
Normal file
10
kapowarr/CHANGELOG.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
## 1.3.1 (19-08-2026)
|
||||||
|
|
||||||
|
- Initial release, based on upstream Kapowarr 1.3.1
|
||||||
|
- Home Assistant ingress support: Kapowarr is started with `--UrlBase /kapowarr` and nginx rewrites
|
||||||
|
that prefix onto the ingress path, so the sidebar panel works without any user configuration
|
||||||
|
- The host, port and URL base are re-applied on every start, so a hosting setting changed by hand
|
||||||
|
in the web interface is repaired by restarting the add-on rather than breaking it permanently
|
||||||
|
- Database and logs stored in the add-on configuration directory, so they survive updates
|
||||||
|
- Temporary downloads redirected to persistent storage (`/config/temp_downloads`)
|
||||||
|
- `PUID`/`PGID`, `TZ`, `env_vars`, local disk and SMB share mounting supported
|
||||||
112
kapowarr/Dockerfile
Normal file
112
kapowarr/Dockerfile
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
#============================#
|
||||||
|
# ALEXBELGIUM'S DOCKERFILE #
|
||||||
|
#============================#
|
||||||
|
# _.------.
|
||||||
|
# _.-` ('>.-`"""-.
|
||||||
|
# '.--'` _'` _ .--.)
|
||||||
|
# -' '-.-';` `
|
||||||
|
# ' - _.' ``'--.
|
||||||
|
# '---` .-'""`
|
||||||
|
# /`
|
||||||
|
#=== Home Assistant Addon ===#
|
||||||
|
|
||||||
|
#################
|
||||||
|
# 1 Build Image #
|
||||||
|
#################
|
||||||
|
|
||||||
|
ARG BUILD_FROM
|
||||||
|
ARG BUILD_VERSION
|
||||||
|
ARG BUILD_UPSTREAM="1.3.1"
|
||||||
|
FROM ${BUILD_FROM}
|
||||||
|
|
||||||
|
##################
|
||||||
|
# 2 Modify Image #
|
||||||
|
##################
|
||||||
|
|
||||||
|
# No S6_* tuning here : the upstream image is a plain python:slim image with no
|
||||||
|
# s6-overlay, so the vars the other addons set would be read by nobody
|
||||||
|
|
||||||
|
##################
|
||||||
|
# 3 Install apps #
|
||||||
|
##################
|
||||||
|
|
||||||
|
# Add rootfs
|
||||||
|
# Absolute paths on purpose : the upstream image sets WORKDIR /app, so the
|
||||||
|
# relative "find ." used by the other addons would miss /etc entirely
|
||||||
|
COPY rootfs/ /
|
||||||
|
RUN find /etc/cont-init.d /etc/services.d -type f \( -name "*.sh" -o -name "run" \) -print -exec chmod +x {} \;
|
||||||
|
|
||||||
|
# Modules
|
||||||
|
ARG MODULES="00-banner.sh 00-global_var.sh 01-custom_script.sh 00-local_mounts.sh 00-smb_mounts.sh"
|
||||||
|
|
||||||
|
# Automatic modules download
|
||||||
|
COPY ha_automodules.sh /ha_automodules.sh
|
||||||
|
RUN chmod 744 /ha_automodules.sh && /ha_automodules.sh "$MODULES" && rm /ha_automodules.sh
|
||||||
|
|
||||||
|
# Manual apps
|
||||||
|
ENV PACKAGES="nginx"
|
||||||
|
|
||||||
|
# Automatic apps & bashio
|
||||||
|
COPY ha_autoapps.sh /ha_autoapps.sh
|
||||||
|
RUN chmod 744 /ha_autoapps.sh && /ha_autoapps.sh "$PACKAGES" && rm /ha_autoapps.sh
|
||||||
|
|
||||||
|
################
|
||||||
|
# 4 Entrypoint #
|
||||||
|
################
|
||||||
|
|
||||||
|
# The upstream image has no s6-overlay, so ha_entrypoint runs as pid 1 : it
|
||||||
|
# executes /etc/cont-init.d, then supervises /etc/services.d. This replaces the
|
||||||
|
# upstream ENTRYPOINT (/app/entrypoint.sh), which is called again from
|
||||||
|
# rootfs/etc/services.d/kapowarr/run so its PUID/PGID handling is kept
|
||||||
|
COPY ha_entrypoint.sh /ha_entrypoint.sh
|
||||||
|
RUN chmod 777 /ha_entrypoint.sh
|
||||||
|
ENTRYPOINT ["/ha_entrypoint.sh"]
|
||||||
|
|
||||||
|
# Install bashio
|
||||||
|
COPY bashio-standalone.sh /usr/local/lib/bashio-standalone.sh
|
||||||
|
RUN chmod 0755 /usr/local/lib/bashio-standalone.sh
|
||||||
|
|
||||||
|
############
|
||||||
|
# 5 Labels #
|
||||||
|
############
|
||||||
|
|
||||||
|
ARG BUILD_ARCH
|
||||||
|
ARG BUILD_DATE
|
||||||
|
ARG BUILD_DESCRIPTION
|
||||||
|
ARG BUILD_NAME
|
||||||
|
ARG BUILD_REF
|
||||||
|
ARG BUILD_REPOSITORY
|
||||||
|
ARG BUILD_VERSION
|
||||||
|
ENV BUILD_VERSION="${BUILD_VERSION}"
|
||||||
|
LABEL \
|
||||||
|
io.hass.name="${BUILD_NAME}" \
|
||||||
|
io.hass.description="${BUILD_DESCRIPTION}" \
|
||||||
|
io.hass.arch="${BUILD_ARCH}" \
|
||||||
|
io.hass.type="addon" \
|
||||||
|
io.hass.version=${BUILD_VERSION} \
|
||||||
|
maintainer="alexbelgium (https://github.com/alexbelgium)" \
|
||||||
|
org.opencontainers.image.title="${BUILD_NAME}" \
|
||||||
|
org.opencontainers.image.description="${BUILD_DESCRIPTION}" \
|
||||||
|
org.opencontainers.image.vendor="Home Assistant Add-ons" \
|
||||||
|
org.opencontainers.image.authors="alexbelgium (https://github.com/alexbelgium)" \
|
||||||
|
org.opencontainers.image.licenses="MIT" \
|
||||||
|
org.opencontainers.image.url="https://github.com/alexbelgium" \
|
||||||
|
org.opencontainers.image.source="https://github.com/${BUILD_REPOSITORY}" \
|
||||||
|
org.opencontainers.image.documentation="https://github.com/${BUILD_REPOSITORY}/blob/main/README.md" \
|
||||||
|
org.opencontainers.image.created=${BUILD_DATE} \
|
||||||
|
org.opencontainers.image.revision=${BUILD_REF} \
|
||||||
|
org.opencontainers.image.version=${BUILD_VERSION}
|
||||||
|
|
||||||
|
#################
|
||||||
|
# 6 Healthcheck #
|
||||||
|
#################
|
||||||
|
|
||||||
|
# Kapowarr is hosted under the /kapowarr url base, see the addon documentation
|
||||||
|
ENV HEALTH_PORT="5656" \
|
||||||
|
HEALTH_URL="/kapowarr/"
|
||||||
|
HEALTHCHECK \
|
||||||
|
--interval=30s \
|
||||||
|
--retries=5 \
|
||||||
|
--start-period=120s \
|
||||||
|
--timeout=25s \
|
||||||
|
CMD curl -A "HealthCheck: Docker/1.0" -s -f "http://127.0.0.1:${HEALTH_PORT}${HEALTH_URL}" >/dev/null 2>&1 || exit 1
|
||||||
81
kapowarr/README.md
Normal file
81
kapowarr/README.md
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
# Home Assistant Add-on: Kapowarr
|
||||||
|
|
||||||
|
Build and manage a comic book library, fitting in the \*arr suite of software.
|
||||||
|
|
||||||
|
[Kapowarr](https://casvt.github.io/Kapowarr/) tracks the volumes you own, finds the issues you are
|
||||||
|
missing, downloads them through GetComics and your download clients, and keeps the files renamed
|
||||||
|
and converted the way you want them.
|
||||||
|
|
||||||
|
## About
|
||||||
|
|
||||||
|
- Import an existing comic collection and match it against ComicVine metadata
|
||||||
|
- Monitor volumes and automatically search for missing issues
|
||||||
|
- Direct downloads and Mega links, plus torrent and Usenet clients
|
||||||
|
- Automatic renaming, converting and file management
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
1. Add this repository to Home Assistant.
|
||||||
|
2. Install the **Kapowarr** add-on.
|
||||||
|
3. Start the add-on and open it from the sidebar (ingress), or on port `5656` at
|
||||||
|
`http://homeassistant:5656/kapowarr` — note the `/kapowarr` suffix, see *Ingress and URLs* below.
|
||||||
|
4. Enter a ComicVine API key under *Settings > Metadata*; Kapowarr cannot search without one.
|
||||||
|
5. Add a root folder under *Settings > Media Management*, for example `/media/comics` or
|
||||||
|
`/share/comics`.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `PUID` / `PGID` | Ownership applied to the add-on configuration directory, and the user Kapowarr runs as. Defaults to `0` (root). |
|
||||||
|
| `TZ` | Timezone, e.g. `Europe/Paris`. |
|
||||||
|
| `localdisks` | Local disks to mount, e.g. `sda1` or a disk label. |
|
||||||
|
| `networkdisks` | SMB shares to mount, e.g. `//192.168.1.2/comics`. Mounted under `/mnt`. |
|
||||||
|
| `cifsusername` / `cifspassword` / `cifsdomain` | Credentials for the SMB shares. |
|
||||||
|
| `smbv1` | Allow the legacy SMBv1 protocol. |
|
||||||
|
| `env_vars` | Extra environment variables passed to Kapowarr. See the [wiki](https://github.com/alexbelgium/hassio-addons/wiki/Add-Environment-variables-to-your-Addon-2). |
|
||||||
|
|
||||||
|
Everything else — root folders, download clients, naming, the ComicVine key — is configured in
|
||||||
|
Kapowarr's own web interface, not in the add-on options.
|
||||||
|
|
||||||
|
The *host*, *port* and *URL base* fields under *Settings > General* are reserved by the add-on and
|
||||||
|
should not be changed. The add-on is built around Kapowarr listening on `0.0.0.0:5656` under the
|
||||||
|
`/kapowarr` URL base, and it sets all three back to those values every time it starts. Changing any
|
||||||
|
of them breaks the sidebar panel and the direct port until the next add-on restart, which repairs
|
||||||
|
them.
|
||||||
|
|
||||||
|
When `PUID`/`PGID` are not `0`, Kapowarr runs as that user and can only read and write the root
|
||||||
|
folders and download folders that user already has access to. The add-on only fixes ownership of
|
||||||
|
its own configuration directory.
|
||||||
|
|
||||||
|
## Ingress and URLs
|
||||||
|
|
||||||
|
Kapowarr is served from the `/kapowarr` subpath so that it works behind Home Assistant ingress:
|
||||||
|
|
||||||
|
- from the Home Assistant sidebar: ingress, no extra setup
|
||||||
|
- directly: `http://homeassistant:5656/kapowarr` — `http://homeassistant:5656/` on its own returns
|
||||||
|
a 404, the subpath is not optional
|
||||||
|
|
||||||
|
External clients that talk to Kapowarr's API must use the direct
|
||||||
|
`http://homeassistant:5656/kapowarr` url. Ingress is browser-session based, so they cannot
|
||||||
|
authenticate through it.
|
||||||
|
|
||||||
|
## Data
|
||||||
|
|
||||||
|
Kapowarr's database (`Kapowarr.db`) and logs live in `/config` inside the add-on, which Home
|
||||||
|
Assistant maps to this add-on's own configuration directory —
|
||||||
|
`/addon_configs/<repository_id>_kapowarr`, browsable with the Filebrowser add-on. They survive
|
||||||
|
add-on updates.
|
||||||
|
|
||||||
|
Temporary downloads go to `/config/temp_downloads` by default, so an interrupted download is not
|
||||||
|
lost when the add-on restarts. That directory is on the Home Assistant data disk: if space there is
|
||||||
|
tight, point *Settings > Download > Direct download temporary folder* at somewhere roomier such as
|
||||||
|
`/share/kapowarr_downloads` or a disk mounted through `localdisks`.
|
||||||
|
|
||||||
|
Your comics themselves stay where you put them, under `/media`, `/share` or a mounted disk.
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
- [Kapowarr upstream project](https://github.com/Casvt/Kapowarr)
|
||||||
|
- [Kapowarr documentation](https://casvt.github.io/Kapowarr/)
|
||||||
|
- [Add-on repository issues](https://github.com/alexbelgium/hassio-addons/issues)
|
||||||
68
kapowarr/apparmor.txt
Normal file
68
kapowarr/apparmor.txt
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
|
||||||
|
#include <tunables/global>
|
||||||
|
|
||||||
|
profile kapowarr_addon flags=(attach_disconnected,mediate_deleted) {
|
||||||
|
#include <abstractions/base>
|
||||||
|
|
||||||
|
capability chown,
|
||||||
|
capability dac_override,
|
||||||
|
capability dac_read_search,
|
||||||
|
capability fowner,
|
||||||
|
capability setgid,
|
||||||
|
capability setuid,
|
||||||
|
capability sys_chroot,
|
||||||
|
capability sys_admin,
|
||||||
|
file,
|
||||||
|
signal,
|
||||||
|
mount,
|
||||||
|
umount,
|
||||||
|
remount,
|
||||||
|
network udp,
|
||||||
|
network tcp,
|
||||||
|
network dgram,
|
||||||
|
network stream,
|
||||||
|
network inet,
|
||||||
|
network inet6,
|
||||||
|
network netlink raw,
|
||||||
|
network unix dgram,
|
||||||
|
|
||||||
|
|
||||||
|
# Entrypoint stack
|
||||||
|
/init ix,
|
||||||
|
/run/{s6,s6-rc*,service}/** ix,
|
||||||
|
/package/** ix,
|
||||||
|
/command/** ix,
|
||||||
|
/run/{,**} rwk,
|
||||||
|
/dev/tty rw,
|
||||||
|
/bin/** ix,
|
||||||
|
/usr/bin/** ix,
|
||||||
|
/usr/lib/bashio/** ix,
|
||||||
|
/etc/s6/** rix,
|
||||||
|
/run/s6/** rix,
|
||||||
|
/etc/services.d/** rwix,
|
||||||
|
/etc/cont-init.d/** rwix,
|
||||||
|
/etc/cont-finish.d/** rwix,
|
||||||
|
/init rix,
|
||||||
|
/var/run/** mrwkl,
|
||||||
|
/var/run/ mrwkl,
|
||||||
|
/dev/i2c-1 mrwkl,
|
||||||
|
# Files required
|
||||||
|
/dev/fuse mrwkl,
|
||||||
|
/dev/sda1 mrwkl,
|
||||||
|
/dev/sdb1 mrwkl,
|
||||||
|
/dev/nvme0 mrwkl,
|
||||||
|
/dev/nvme1 mrwkl,
|
||||||
|
/dev/mmcblk0p1 mrwkl,
|
||||||
|
/dev/* mrwkl,
|
||||||
|
/tmp/** mrkwl,
|
||||||
|
|
||||||
|
# Data access
|
||||||
|
/data/** rw,
|
||||||
|
|
||||||
|
# suppress ptrace denials when using 'docker ps' or using 'ps' inside a container
|
||||||
|
ptrace (trace,read) peer=docker-default,
|
||||||
|
|
||||||
|
# docker daemon confinement requires explicit allow rule for signal
|
||||||
|
signal (receive) set=(kill,term) peer=/usr/bin/docker,
|
||||||
|
|
||||||
|
}
|
||||||
6
kapowarr/build.json
Normal file
6
kapowarr/build.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"build_from": {
|
||||||
|
"aarch64": "mrcas/kapowarr:v1.3.1",
|
||||||
|
"amd64": "mrcas/kapowarr:v1.3.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
107
kapowarr/config.yaml
Normal file
107
kapowarr/config.yaml
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
arch:
|
||||||
|
- aarch64
|
||||||
|
- amd64
|
||||||
|
backup_exclude:
|
||||||
|
- "**/logs/*"
|
||||||
|
- "**/temp_downloads/*"
|
||||||
|
description: Comic book library manager, fitting in the *arr suite of software
|
||||||
|
devices:
|
||||||
|
- /dev/dri
|
||||||
|
- /dev/dri/card0
|
||||||
|
- /dev/dri/card1
|
||||||
|
- /dev/dri/renderD128
|
||||||
|
- /dev/vchiq
|
||||||
|
- /dev/video10
|
||||||
|
- /dev/video11
|
||||||
|
- /dev/video12
|
||||||
|
- /dev/video13
|
||||||
|
- /dev/video14
|
||||||
|
- /dev/video15
|
||||||
|
- /dev/video16
|
||||||
|
- /dev/ttyUSB0
|
||||||
|
- /dev/sda
|
||||||
|
- /dev/sdb
|
||||||
|
- /dev/sdc
|
||||||
|
- /dev/sdd
|
||||||
|
- /dev/sde
|
||||||
|
- /dev/sdf
|
||||||
|
- /dev/sdg
|
||||||
|
- /dev/nvme
|
||||||
|
- /dev/nvme0
|
||||||
|
- /dev/nvme0n1
|
||||||
|
- /dev/nvme0n1p1
|
||||||
|
- /dev/nvme0n1p2
|
||||||
|
- /dev/nvme0n1p3
|
||||||
|
- /dev/nvme1n1
|
||||||
|
- /dev/nvme1n1p1
|
||||||
|
- /dev/nvme1n1p2
|
||||||
|
- /dev/nvme1n1p3
|
||||||
|
- /dev/nvme2n1
|
||||||
|
- /dev/nvme2n1p1
|
||||||
|
- /dev/nvme2n1p2
|
||||||
|
- /dev/nvme2n1p3
|
||||||
|
- /dev/mmcblk
|
||||||
|
- /dev/fuse
|
||||||
|
- /dev/sda1
|
||||||
|
- /dev/sdb1
|
||||||
|
- /dev/sdc1
|
||||||
|
- /dev/sdd1
|
||||||
|
- /dev/sde1
|
||||||
|
- /dev/sdf1
|
||||||
|
- /dev/sdg1
|
||||||
|
- /dev/sda2
|
||||||
|
- /dev/sdb2
|
||||||
|
- /dev/sdc2
|
||||||
|
- /dev/sdd2
|
||||||
|
- /dev/sde2
|
||||||
|
- /dev/sdf2
|
||||||
|
- /dev/sdg2
|
||||||
|
- /dev/sda3
|
||||||
|
- /dev/sdb3
|
||||||
|
- /dev/sda4
|
||||||
|
- /dev/sdb4
|
||||||
|
- /dev/sda5
|
||||||
|
- /dev/sda6
|
||||||
|
- /dev/sda7
|
||||||
|
- /dev/sda8
|
||||||
|
- /dev/nvme0
|
||||||
|
- /dev/nvme1
|
||||||
|
- /dev/nvme2
|
||||||
|
image: ghcr.io/alexbelgium/kapowarr-{arch}
|
||||||
|
ingress: true
|
||||||
|
ingress_entry: kapowarr
|
||||||
|
init: false
|
||||||
|
map:
|
||||||
|
- addon_config:rw
|
||||||
|
- media:rw
|
||||||
|
- share:rw
|
||||||
|
name: Kapowarr
|
||||||
|
options:
|
||||||
|
env_vars: []
|
||||||
|
PGID: 0
|
||||||
|
PUID: 0
|
||||||
|
panel_icon: mdi:book-multiple
|
||||||
|
ports:
|
||||||
|
5656/tcp: 5656
|
||||||
|
ports_description:
|
||||||
|
5656/tcp: Web interface (path /kapowarr)
|
||||||
|
privileged:
|
||||||
|
- SYS_ADMIN
|
||||||
|
- DAC_READ_SEARCH
|
||||||
|
schema:
|
||||||
|
env_vars:
|
||||||
|
- name: match(^[A-Za-z0-9_]+$)
|
||||||
|
value: str?
|
||||||
|
PGID: int
|
||||||
|
PUID: int
|
||||||
|
TZ: str?
|
||||||
|
cifsdomain: str?
|
||||||
|
cifspassword: str?
|
||||||
|
cifsusername: str?
|
||||||
|
localdisks: str?
|
||||||
|
networkdisks: str?
|
||||||
|
smbv1: bool?
|
||||||
|
slug: kapowarr
|
||||||
|
udev: true
|
||||||
|
url: https://github.com/alexbelgium/hassio-addons/tree/master/kapowarr
|
||||||
|
version: "1.3.1"
|
||||||
BIN
kapowarr/icon.png
Normal file
BIN
kapowarr/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
BIN
kapowarr/logo.png
Normal file
BIN
kapowarr/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
35
kapowarr/rootfs/etc/cont-init.d/20-config_location.sh
Executable file
35
kapowarr/rootfs/etc/cont-init.d/20-config_location.sh
Executable file
@@ -0,0 +1,35 @@
|
|||||||
|
#!/usr/bin/with-contenv bashio
|
||||||
|
# shellcheck shell=bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Kapowarr keeps its database, its logs and its temporary downloads outside the
|
||||||
|
# image so that they survive the container being recreated.
|
||||||
|
#
|
||||||
|
# The database and log folders are passed on the command line (see
|
||||||
|
# /etc/services.d/kapowarr/run). The temporary download folder is not: upstream
|
||||||
|
# re-applies --TempDownloadFolder on every start Kapowarr makes, including the
|
||||||
|
# self-restarts it performs after a hosting change, so passing it would keep
|
||||||
|
# undoing a folder the user picked in Settings > Download. Symlinking upstream's
|
||||||
|
# default onto persistent storage gives the same persistence and leaves the
|
||||||
|
# setting itself entirely to the user.
|
||||||
|
|
||||||
|
CONFIG_LOCATION="/config"
|
||||||
|
bashio::log.info "Config stored in $CONFIG_LOCATION"
|
||||||
|
|
||||||
|
mkdir -p "$CONFIG_LOCATION/logs" "$CONFIG_LOCATION/temp_downloads"
|
||||||
|
|
||||||
|
# Compared against the target rather than just testing for a symlink, so that a
|
||||||
|
# link left pointing somewhere else -- by a future upstream image, or by hand --
|
||||||
|
# is repaired instead of silently kept.
|
||||||
|
if [ "$(readlink /app/temp_downloads)" != "$CONFIG_LOCATION/temp_downloads" ]; then
|
||||||
|
rm -rf /app/temp_downloads
|
||||||
|
ln -s "$CONFIG_LOCATION/temp_downloads" /app/temp_downloads
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Numbered 20- on purpose : it must sort after 00-global_var.sh, which is what
|
||||||
|
# exports PUID/PGID from the addon options. The upstream image sets both to 0,
|
||||||
|
# so the fallbacks only apply when the module is absent.
|
||||||
|
# Recursive because a user raising PUID after the first run would otherwise
|
||||||
|
# leave Kapowarr.db, its -wal/-shm sidecars and the logs owned by the previous
|
||||||
|
# uid, which sqlite then cannot write.
|
||||||
|
chown -R "${PUID:-0}:${PGID:-0}" "$CONFIG_LOCATION"
|
||||||
17
kapowarr/rootfs/etc/cont-init.d/32-nginx_ingress.sh
Executable file
17
kapowarr/rootfs/etc/cont-init.d/32-nginx_ingress.sh
Executable file
@@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/with-contenv bashio
|
||||||
|
# shellcheck shell=bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
#################
|
||||||
|
# NGINX SETTING #
|
||||||
|
#################
|
||||||
|
declare ingress_interface
|
||||||
|
declare ingress_port
|
||||||
|
declare ingress_entry
|
||||||
|
|
||||||
|
ingress_port=$(bashio::addon.ingress_port)
|
||||||
|
ingress_interface=$(bashio::addon.ip_address)
|
||||||
|
ingress_entry=$(bashio::addon.ingress_entry)
|
||||||
|
sed -i "s/%%port%%/${ingress_port}/g" /etc/nginx/servers/ingress.conf
|
||||||
|
sed -i "s/%%interface%%/${ingress_interface}/g" /etc/nginx/servers/ingress.conf
|
||||||
|
sed -i "s|%%ingress_entry%%|${ingress_entry}|g" /etc/nginx/servers/ingress.conf
|
||||||
96
kapowarr/rootfs/etc/nginx/includes/mime.types
Normal file
96
kapowarr/rootfs/etc/nginx/includes/mime.types
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
types {
|
||||||
|
text/html html htm shtml;
|
||||||
|
text/css css;
|
||||||
|
text/xml xml;
|
||||||
|
image/gif gif;
|
||||||
|
image/jpeg jpeg jpg;
|
||||||
|
application/javascript js;
|
||||||
|
application/atom+xml atom;
|
||||||
|
application/rss+xml rss;
|
||||||
|
|
||||||
|
text/mathml mml;
|
||||||
|
text/plain txt;
|
||||||
|
text/vnd.sun.j2me.app-descriptor jad;
|
||||||
|
text/vnd.wap.wml wml;
|
||||||
|
text/x-component htc;
|
||||||
|
|
||||||
|
image/png png;
|
||||||
|
image/svg+xml svg svgz;
|
||||||
|
image/tiff tif tiff;
|
||||||
|
image/vnd.wap.wbmp wbmp;
|
||||||
|
image/webp webp;
|
||||||
|
image/x-icon ico;
|
||||||
|
image/x-jng jng;
|
||||||
|
image/x-ms-bmp bmp;
|
||||||
|
|
||||||
|
font/woff woff;
|
||||||
|
font/woff2 woff2;
|
||||||
|
|
||||||
|
application/java-archive jar war ear;
|
||||||
|
application/json json;
|
||||||
|
application/mac-binhex40 hqx;
|
||||||
|
application/msword doc;
|
||||||
|
application/pdf pdf;
|
||||||
|
application/postscript ps eps ai;
|
||||||
|
application/rtf rtf;
|
||||||
|
application/vnd.apple.mpegurl m3u8;
|
||||||
|
application/vnd.google-earth.kml+xml kml;
|
||||||
|
application/vnd.google-earth.kmz kmz;
|
||||||
|
application/vnd.ms-excel xls;
|
||||||
|
application/vnd.ms-fontobject eot;
|
||||||
|
application/vnd.ms-powerpoint ppt;
|
||||||
|
application/vnd.oasis.opendocument.graphics odg;
|
||||||
|
application/vnd.oasis.opendocument.presentation odp;
|
||||||
|
application/vnd.oasis.opendocument.spreadsheet ods;
|
||||||
|
application/vnd.oasis.opendocument.text odt;
|
||||||
|
application/vnd.openxmlformats-officedocument.presentationml.presentation
|
||||||
|
pptx;
|
||||||
|
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
||||||
|
xlsx;
|
||||||
|
application/vnd.openxmlformats-officedocument.wordprocessingml.document
|
||||||
|
docx;
|
||||||
|
application/vnd.wap.wmlc wmlc;
|
||||||
|
application/x-7z-compressed 7z;
|
||||||
|
application/x-cocoa cco;
|
||||||
|
application/x-java-archive-diff jardiff;
|
||||||
|
application/x-java-jnlp-file jnlp;
|
||||||
|
application/x-makeself run;
|
||||||
|
application/x-perl pl pm;
|
||||||
|
application/x-pilot prc pdb;
|
||||||
|
application/x-rar-compressed rar;
|
||||||
|
application/x-redhat-package-manager rpm;
|
||||||
|
application/x-sea sea;
|
||||||
|
application/x-shockwave-flash swf;
|
||||||
|
application/x-stuffit sit;
|
||||||
|
application/x-tcl tcl tk;
|
||||||
|
application/x-x509-ca-cert der pem crt;
|
||||||
|
application/x-xpinstall xpi;
|
||||||
|
application/xhtml+xml xhtml;
|
||||||
|
application/xspf+xml xspf;
|
||||||
|
application/zip zip;
|
||||||
|
|
||||||
|
application/octet-stream bin exe dll;
|
||||||
|
application/octet-stream deb;
|
||||||
|
application/octet-stream dmg;
|
||||||
|
application/octet-stream iso img;
|
||||||
|
application/octet-stream msi msp msm;
|
||||||
|
|
||||||
|
audio/midi mid midi kar;
|
||||||
|
audio/mpeg mp3;
|
||||||
|
audio/ogg ogg;
|
||||||
|
audio/x-m4a m4a;
|
||||||
|
audio/x-realaudio ra;
|
||||||
|
|
||||||
|
video/3gpp 3gpp 3gp;
|
||||||
|
video/mp2t ts;
|
||||||
|
video/mp4 mp4;
|
||||||
|
video/mpeg mpeg mpg;
|
||||||
|
video/quicktime mov;
|
||||||
|
video/webm webm;
|
||||||
|
video/x-flv flv;
|
||||||
|
video/x-m4v m4v;
|
||||||
|
video/x-mng mng;
|
||||||
|
video/x-ms-asf asx asf;
|
||||||
|
video/x-ms-wmv wmv;
|
||||||
|
video/x-msvideo avi;
|
||||||
|
}
|
||||||
1
kapowarr/rootfs/etc/nginx/includes/resolver.conf
Normal file
1
kapowarr/rootfs/etc/nginx/includes/resolver.conf
Normal file
@@ -0,0 +1 @@
|
|||||||
|
resolver 127.0.0.11 ipv6=off;
|
||||||
56
kapowarr/rootfs/etc/nginx/nginx.conf
Normal file
56
kapowarr/rootfs/etc/nginx/nginx.conf
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
|
||||||
|
# Run nginx in foreground.
|
||||||
|
daemon off;
|
||||||
|
|
||||||
|
# This is run inside Docker.
|
||||||
|
user root;
|
||||||
|
|
||||||
|
# Pid storage location.
|
||||||
|
pid /var/run/nginx.pid;
|
||||||
|
|
||||||
|
# Set number of worker processes.
|
||||||
|
worker_processes 1;
|
||||||
|
|
||||||
|
# Enables the use of JIT for regular expressions to speed-up their processing.
|
||||||
|
pcre_jit on;
|
||||||
|
|
||||||
|
# Write error log to Hass.io add-on log.
|
||||||
|
error_log /proc/1/fd/1 error;
|
||||||
|
|
||||||
|
# Load allowed environment vars
|
||||||
|
env HASSIO_TOKEN;
|
||||||
|
|
||||||
|
# Load dynamic modules.
|
||||||
|
include /etc/nginx/modules-enabled/*.conf;
|
||||||
|
|
||||||
|
# Max num of simultaneous connections by a worker process.
|
||||||
|
events {
|
||||||
|
worker_connections 512;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
include /etc/nginx/includes/mime.types;
|
||||||
|
|
||||||
|
log_format hassio '[$time_local] $status '
|
||||||
|
'$http_x_forwarded_for($remote_addr) '
|
||||||
|
'$request ($http_user_agent)';
|
||||||
|
|
||||||
|
access_log /proc/1/fd/1 hassio;
|
||||||
|
client_max_body_size 4G;
|
||||||
|
default_type application/octet-stream;
|
||||||
|
gzip on;
|
||||||
|
keepalive_timeout 65;
|
||||||
|
sendfile on;
|
||||||
|
server_tokens off;
|
||||||
|
tcp_nodelay on;
|
||||||
|
tcp_nopush on;
|
||||||
|
|
||||||
|
map $http_upgrade $connection_upgrade {
|
||||||
|
default upgrade;
|
||||||
|
'' close;
|
||||||
|
}
|
||||||
|
|
||||||
|
include /etc/nginx/includes/resolver.conf;
|
||||||
|
|
||||||
|
include /etc/nginx/servers/*.conf;
|
||||||
|
}
|
||||||
56
kapowarr/rootfs/etc/nginx/servers/ingress.conf
Normal file
56
kapowarr/rootfs/etc/nginx/servers/ingress.conf
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
server {
|
||||||
|
listen %%interface%%:%%port%% default_server;
|
||||||
|
|
||||||
|
client_max_body_size 0;
|
||||||
|
|
||||||
|
# Kapowarr is mounted under the /kapowarr url base, so Werkzeug's
|
||||||
|
# DispatcherMiddleware answers 404 at / . Home Assistant opens the ingress
|
||||||
|
# panel at <ingress_entry>/ unless config.yaml's ingress_entry moves it, so
|
||||||
|
# bounce / to the url base whichever way the panel was opened.
|
||||||
|
# absolute_redirect off keeps the Location relative to the HA host instead
|
||||||
|
# of nginx's own listen address.
|
||||||
|
location = / {
|
||||||
|
absolute_redirect off;
|
||||||
|
return 302 %%ingress_entry%%/kapowarr/;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
add_header Access-Control-Allow-Origin *;
|
||||||
|
proxy_connect_timeout 30m;
|
||||||
|
proxy_send_timeout 30m;
|
||||||
|
proxy_read_timeout 30m;
|
||||||
|
proxy_pass http://127.0.0.1:5656;
|
||||||
|
|
||||||
|
# Kapowarr streams queue, task and download progress over socket.io at
|
||||||
|
# <url_base>/api/socket.io, which must not be buffered or the UI stops
|
||||||
|
# updating until the buffer fills
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection $connection_upgrade;
|
||||||
|
|
||||||
|
# Werkzeug redirects /kapowarr to /kapowarr/ , and the Location it
|
||||||
|
# produces is absolute against the upstream address nginx talks to.
|
||||||
|
# proxy_redirect puts it back on the ingress path (the second rule
|
||||||
|
# covers an already relative Location).
|
||||||
|
absolute_redirect off;
|
||||||
|
proxy_redirect http://127.0.0.1:5656/ %%ingress_entry%%/;
|
||||||
|
proxy_redirect / %%ingress_entry%%/;
|
||||||
|
|
||||||
|
# Kapowarr renders every link and asset url as {{url_base}}/... and
|
||||||
|
# general.js reads the same value back out of
|
||||||
|
# <meta id="url_base" data-value="/kapowarr">, so rewriting the html
|
||||||
|
# moves the whole SPA -- including its fetch() and socket.io urls --
|
||||||
|
# onto the ingress prefix that Home Assistant strips before forwarding.
|
||||||
|
# sub_filter cannot rewrite a compressed body, hence Accept-Encoding "".
|
||||||
|
proxy_set_header Accept-Encoding "";
|
||||||
|
sub_filter_once off;
|
||||||
|
# text/html is always filtered ; the pwa manifest is added because
|
||||||
|
# /manifest.json embeds the url base in start_url, scope, id and icons,
|
||||||
|
# and it is served as application/manifest+json. Json is deliberately
|
||||||
|
# not filtered : api payloads carry user file paths that must not be
|
||||||
|
# rewritten.
|
||||||
|
sub_filter_types application/manifest+json;
|
||||||
|
sub_filter "/kapowarr" "%%ingress_entry%%/kapowarr";
|
||||||
|
}
|
||||||
|
}
|
||||||
36
kapowarr/rootfs/etc/services.d/kapowarr/run
Executable file
36
kapowarr/rootfs/etc/services.d/kapowarr/run
Executable file
@@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/with-contenv bashio
|
||||||
|
# shellcheck shell=bash
|
||||||
|
set -e
|
||||||
|
# ==============================================================================
|
||||||
|
|
||||||
|
# Kapowarr is started through the upstream entrypoint, which is what implements
|
||||||
|
# PUID/PGID (groupmod -o / usermod -o, then gosu). ha_entrypoint.sh replaced it
|
||||||
|
# as the container entrypoint so that cont-init.d and nginx could run too, so it
|
||||||
|
# is called again here rather than reimplemented. Both usermod and groupmod are
|
||||||
|
# given -o upstream, so a PUID that collides with an existing account is not an
|
||||||
|
# error.
|
||||||
|
#
|
||||||
|
# --UrlBase is what makes ingress work: Kapowarr renders absolute urls, Home
|
||||||
|
# Assistant strips its own ingress prefix before forwarding, and nginx adds it
|
||||||
|
# back by rewriting this fixed prefix. See rootfs/etc/nginx/servers/ingress.conf.
|
||||||
|
#
|
||||||
|
# --Host and --Port are passed for the same reason, even though they are already
|
||||||
|
# the upstream defaults: all three are stored in the database, and Kapowarr reads
|
||||||
|
# the stored value when the flag is absent. Without them, a host or port changed
|
||||||
|
# in Settings > General would survive every restart and upgrade while nginx and
|
||||||
|
# the healthcheck stayed pointed at 127.0.0.1:5656 -- a permanent 502 with no way
|
||||||
|
# back except editing the database. Passing all three makes the whole hosting
|
||||||
|
# section self repairing.
|
||||||
|
#
|
||||||
|
# Upstream applies these three only on a startup, never on the restarts Kapowarr
|
||||||
|
# performs itself, so they are re-applied once per container start and do not
|
||||||
|
# fight the user in between.
|
||||||
|
|
||||||
|
bashio::log.info "Starting Kapowarr (served on the /kapowarr path, see the addon documentation)"
|
||||||
|
|
||||||
|
exec /app/entrypoint.sh python3 /app/Kapowarr.py \
|
||||||
|
--DatabaseFolder /config \
|
||||||
|
--LogFolder /config/logs \
|
||||||
|
--Host 0.0.0.0 \
|
||||||
|
--Port 5656 \
|
||||||
|
--UrlBase /kapowarr
|
||||||
36
kapowarr/rootfs/etc/services.d/nginx/run
Executable file
36
kapowarr/rootfs/etc/services.d/nginx/run
Executable file
@@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/with-contenv bashio
|
||||||
|
# shellcheck shell=bash
|
||||||
|
set -e
|
||||||
|
# ==============================================================================
|
||||||
|
|
||||||
|
# Wait for Kapowarr to answer before nginx starts serving ingress. The first
|
||||||
|
# boot creates the database and runs its migrations, so leave a wide margin, but
|
||||||
|
# poll rather than call bashio::net.wait_for : bashio takes (port host timeout)
|
||||||
|
# while the bundled bashio-standalone.sh takes (host port timeout), and picking
|
||||||
|
# the wrong one would either fail instantly or block for the whole timeout.
|
||||||
|
# The per probe timeouts keep the ceiling real : without them a half open
|
||||||
|
# connection would hang a single probe, and the loop, forever.
|
||||||
|
# A wall clock deadline, not an attempt count : a failed probe costs up to
|
||||||
|
# max-time on top of the sleep, so counting attempts would stretch the wait to
|
||||||
|
# roughly twice the advertised ceiling.
|
||||||
|
# The probe asks for /kapowarr/ rather than / , because / is served by the empty
|
||||||
|
# app that DispatcherMiddleware mounts beside the url base and always answers.
|
||||||
|
kapowarr_ready=false
|
||||||
|
deadline=$((SECONDS + 300))
|
||||||
|
while [ "$SECONDS" -lt "$deadline" ]; do
|
||||||
|
if curl -sf --connect-timeout 2 --max-time 5 -o /dev/null "http://127.0.0.1:5656/kapowarr/"; then
|
||||||
|
kapowarr_ready=true
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
|
||||||
|
# Deliberately not fatal : nginx serving a 502 tells the user something is wrong
|
||||||
|
# and starts working by itself once Kapowarr finally answers, while refusing to
|
||||||
|
# start would take ingress down for good after ha_entrypoint gives up retrying.
|
||||||
|
if [ "$kapowarr_ready" != true ]; then
|
||||||
|
bashio::log.warning "Kapowarr did not answer within 5 minutes. Starting NGinx anyway : ingress will return 502 until it does."
|
||||||
|
fi
|
||||||
|
|
||||||
|
bashio::log.info "Starting NGinx..."
|
||||||
|
exec nginx
|
||||||
9
kapowarr/updater.json
Normal file
9
kapowarr/updater.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"github_beta": "false",
|
||||||
|
"last_update": "2026-08-19",
|
||||||
|
"repository": "alexbelgium/hassio-addons",
|
||||||
|
"slug": "kapowarr",
|
||||||
|
"source": "github",
|
||||||
|
"upstream_repo": "Casvt/Kapowarr",
|
||||||
|
"upstream_version": "1.3.1"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user