Compare commits

..

1 Commits

Author SHA1 Message Date
alexbelgium
41f76f0d29 fix: auto-fix linting issues 2025-11-23 00:35:42 +00:00
172 changed files with 515 additions and 702 deletions

View File

@@ -197,7 +197,6 @@ Fabian-Eigenherd,Germany
Faithfinder,Canada Faithfinder,Canada
FallsSteven, FallsSteven,
Felitendo, Felitendo,
Filipza,
Flipsoo, Flipsoo,
FloppiTuna,United States FloppiTuna,United States
Fluffy-Bunny-23, Fluffy-Bunny-23,
@@ -488,7 +487,6 @@ Rapozillha,Portugal
Raw2x2, Raw2x2,
RdN-J, RdN-J,
RealJustMe, RealJustMe,
Redmno,
Reiqu,Germany Reiqu,Germany
RemcoSchrijver,Netherlands RemcoSchrijver,Netherlands
Rene2302, Rene2302,
@@ -496,7 +494,6 @@ RescueWolf-Dreamwalker,
RhaaKaye, RhaaKaye,
RicLund,Canada RicLund,Canada
Richyread, Richyread,
RimmeVG,
Rimpla, Rimpla,
Robbot,Ireland Robbot,Ireland
RobertZwets, RobertZwets,
@@ -584,7 +581,6 @@ Syuq,
T-I-M-O-T, T-I-M-O-T,
TCTnz, TCTnz,
THENEXTBIGTIME, THENEXTBIGTIME,
TS-1709,
TarrX,Germany TarrX,Germany
Tche333, Tche333,
Tchoupinax, Tchoupinax,
@@ -818,7 +814,6 @@ bigsby-exe,United Kingdom
bilak,Czechia bilak,Czechia
bitDealer, bitDealer,
bjackerman,United States bjackerman,United States
bjoe10,
bkuri,Mexico bkuri,Mexico
blackshoals, blackshoals,
blairun, blairun,
@@ -951,7 +946,6 @@ ctrlaltprocrastinate,
ctyfrank, ctyfrank,
cuza,Cuba cuza,Cuba
cvladan, cvladan,
cvroque,
cwmoriarty, cwmoriarty,
cy1798, cy1798,
cyberjohn60, cyberjohn60,
@@ -1057,7 +1051,6 @@ dtrochow,
duckduckuk,United Kingdom duckduckuk,United Kingdom
duhaijian, duhaijian,
dumbledorethor, dumbledorethor,
dutzi88,
duydo,Viet Nam duydo,Viet Nam
dwainegallimore,United Kingdom dwainegallimore,United Kingdom
dykandDK, dykandDK,
@@ -1101,7 +1094,6 @@ ettoreboy,
euneuneu, euneuneu,
evalevil,China evalevil,China
everconnectcn, everconnectcn,
everestlion,
evertonerik, evertonerik,
evnb,United States evnb,United States
excodex,United Kingdom excodex,United Kingdom
@@ -1366,7 +1358,6 @@ jokob-sk,
joluas, joluas,
jonaslang1,Germany jonaslang1,Germany
jonathanweinberg, jonathanweinberg,
jonbeckman,
jonssonjunior94, jonssonjunior94,
joostiphone, joostiphone,
jopacar1, jopacar1,
@@ -1968,7 +1959,6 @@ starbuck93,United States
steef84, steef84,
stef-th, stef-th,
stefangries, stefangries,
steinmaerivoet,Belgium
stephenjharrington, stephenjharrington,
stepping-razor,Czechia stepping-razor,Czechia
stetho,United Kingdom stetho,United Kingdom
@@ -2189,6 +2179,5 @@ zjw57,China
zking7, zking7,
zonorti,Germany zonorti,Germany
zr-idt, zr-idt,
zuranthus,Sweden
zweehn, zweehn,
zymotik,Germany zymotik,Germany
1 username country
197 Faithfinder Canada
198 FallsSteven
199 Felitendo
Filipza
200 Flipsoo
201 FloppiTuna United States
202 Fluffy-Bunny-23
487 Raw2x2
488 RdN-J
489 RealJustMe
Redmno
490 Reiqu Germany
491 RemcoSchrijver Netherlands
492 Rene2302
494 RhaaKaye
495 RicLund Canada
496 Richyread
RimmeVG
497 Rimpla
498 Robbot Ireland
499 RobertZwets
581 T-I-M-O-T
582 TCTnz
583 THENEXTBIGTIME
TS-1709
584 TarrX Germany
585 Tche333
586 Tchoupinax
814 bilak Czechia
815 bitDealer
816 bjackerman United States
bjoe10
817 bkuri Mexico
818 blackshoals
819 blairun
946 ctyfrank
947 cuza Cuba
948 cvladan
cvroque
949 cwmoriarty
950 cy1798
951 cyberjohn60
1051 duckduckuk United Kingdom
1052 duhaijian
1053 dumbledorethor
dutzi88
1054 duydo Viet Nam
1055 dwainegallimore United Kingdom
1056 dykandDK
1094 euneuneu
1095 evalevil China
1096 everconnectcn
everestlion
1097 evertonerik
1098 evnb United States
1099 excodex United Kingdom
1358 joluas
1359 jonaslang1 Germany
1360 jonathanweinberg
jonbeckman
1361 jonssonjunior94
1362 joostiphone
1363 jopacar1
1959 steef84
1960 stef-th
1961 stefangries
steinmaerivoet Belgium
1962 stephenjharrington
1963 stepping-razor Czechia
1964 stetho United Kingdom
2179 zking7
2180 zonorti Germany
2181 zr-idt
zuranthus Sweden
2182 zweehn
2183 zymotik Germany

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 61 KiB

BIN
.github/stats.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -112,6 +112,7 @@ def automatic_mqtt_publish(file, detection, path):
mqttc.publish(mqtt_topic, json_bird, 1) mqttc.publish(mqtt_topic, json_bird, 1)
log.info("Posted to MQTT: ok") log.info("Posted to MQTT: ok")
# Create MQTT client using legacy callback API when available for # Create MQTT client using legacy callback API when available for
# compatibility with paho-mqtt >= 2.0 # compatibility with paho-mqtt >= 2.0
callback_api = getattr(mqtt, "CallbackAPIVersion", None) callback_api = getattr(mqtt, "CallbackAPIVersion", None)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

0
emby/rootfs/etc/services.d/nginx/run Normal file → Executable file
View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -1,11 +1,4 @@
## debian-2025-11-19 (2025-11-19)
- Recreate a default config.json when only a legacy config.yaml is present so upgrades keep a usable configuration file
## debian-2025-11-18 (2025-11-18)
- Restore the default configuration template to config.json with the expected sample values
- Recreate a default config.json when only a legacy config.yaml is present so upgrades keep a usable configuration file
## debian-2025-11-16 (2025-11-16) ## debian-2025-11-16 (2025-11-16)
- Update to latest version from charlocharlie/epicgames-freegames - Update to latest version from charlocharlie/epicgames-freegames
## "debian-2025-11-09" (09-11-2025) ## "debian-2025-11-09" (09-11-2025)

View File

@@ -28,13 +28,13 @@ This addon is based on the docker image https://hub.docker.com/r/charlocharlie/e
## Configuration ## Configuration
Addon options expose the `env_vars` field for passing extra environment variables; all other configuration is done via the JSON file. Addon options expose the `env_vars` field for passing extra environment variables; all other configuration is done via JSON files.
### Configuration Files ### Configuration Files
Configuration files are stored in `/config/addons_config/epicgamesfree/`: Configuration files are stored in `/config/addons_config/epicgamesfree/`:
- **config.json**: Main configuration file - **config.yaml**: Main configuration file
- **cookies.json**: Authentication cookies (optional) - **cookies.json**: Authentication cookies (optional)
If these files don't exist, they will be created at first boot with default settings. If these files don't exist, they will be created at first boot with default settings.
@@ -43,16 +43,10 @@ If these files don't exist, they will be created at first boot with default sett
### Basic Configuration ### Basic Configuration
Create `/config/addons_config/epicgamesfree/config.json`: Create `/config/addons_config/epicgamesfree/config.yaml`:
```json ```json
{ {
"runOnStartup": true,
"cronSchedule": "0 */6 * * *",
"logLevel": "info",
"webPortalConfig": {
"baseUrl": "https://epic.example.com"
},
"accounts": [ "accounts": [
{ {
"email": "your-epic-email@example.com", "email": "your-epic-email@example.com",
@@ -60,9 +54,12 @@ Create `/config/addons_config/epicgamesfree/config.json`:
"totp": "OPTIONAL_2FA_SECRET" "totp": "OPTIONAL_2FA_SECRET"
} }
], ],
"notifiers": [ "intervalHours": 24,
{ "onlyWeekly": false,
"type": "email", "searchStrategy": "purchase",
"browserNavigationTimeout": 300000,
"notifications": {
"email": {
"smtpHost": "smtp.gmail.com", "smtpHost": "smtp.gmail.com",
"smtpPort": 587, "smtpPort": 587,
"emailSenderAddress": "notifications@example.com", "emailSenderAddress": "notifications@example.com",
@@ -74,7 +71,7 @@ Create `/config/addons_config/epicgamesfree/config.json`:
"pass": "your-app-password" "pass": "your-app-password"
} }
} }
] }
} }
``` ```
@@ -83,52 +80,51 @@ Create `/config/addons_config/epicgamesfree/config.json`:
| Option | Type | Description | | Option | Type | Description |
|--------|------|-------------| |--------|------|-------------|
| `accounts` | array | List of Epic Games accounts | | `accounts` | array | List of Epic Games accounts |
| `cronSchedule` | string | Cron schedule to claim games (default: `0 */6 * * *`) | | `intervalHours` | number | Check interval in hours (default: 24) |
| `runOnStartup` | boolean | Run a claim cycle when the add-on starts | | `onlyWeekly` | boolean | Only claim weekly free games |
| `logLevel` | string | Application log level | | `searchStrategy` | string | Search strategy: "purchase" or "claim" |
| `webPortalConfig.baseUrl` | string | Base URL used by the included web portal | | `browserNavigationTimeout` | number | Browser timeout in milliseconds |
| `notifiers` | array | Notification targets such as email, Discord, Telegram, Apprise, etc. | | `notifications` | object | Notification settings (email, webhook, etc.) |
### Account Configuration ### Account Configuration
For each account in the `accounts` array: For each account in the `accounts` array:
```yaml ```json
email: account@example.com {
password: password "email": "account@example.com",
totp: TOTP_SECRET "password": "password",
onlyWeekly: true "totp": "TOTP_SECRET",
"onlyWeekly": true
}
``` ```
### Notification Methods ### Notification Methods
#### Email Notifications #### Email Notifications
```yaml ```json
notifications: "notifications": {
email: "email": {
smtpHost: smtp.gmail.com "smtpHost": "smtp.gmail.com",
smtpPort: 587 "smtpPort": 587,
emailSenderAddress: sender@example.com "emailSenderAddress": "sender@example.com",
emailRecipientAddress: recipient@example.com "emailRecipientAddress": "recipient@example.com",
secure: false "secure": false,
auth: "auth": {
user: sender@example.com "user": "sender@example.com",
pass: app-password "pass": "app-password"
}
}
}
``` ```
#### Webhook Notifications #### Webhook Notifications
```json ```json
{ "notifications": {
"notifiers": [ "webhook": {
{
"type": "webhook",
"url": "https://your-webhook-url.com", "url": "https://your-webhook-url.com",
"events": [ "events": ["purchase-success", "already-owned"]
"purchase-success",
"already-owned"
]
} }
]
} }
``` ```
@@ -148,11 +144,9 @@ For detailed cookie import instructions, see: https://github.com/claabs/epicgame
### Troubleshooting ### Troubleshooting
#### Timeout Errors #### Timeout Errors
Add the following to your config.json: Add the following to your config.yaml:
```json ```json
{ "browserNavigationTimeout": 300000
"browserNavigationTimeout": 300000
}
``` ```
#### Login Issues #### Login Issues
@@ -178,7 +172,7 @@ The installation of this add-on is pretty straightforward and not different in c
### Timeout error ### Timeout error
Please try adding `"browserNavigationTimeout": 300000,` to your config.json (https://github.com/alexbelgium/hassio-addons/issues/675#issuecomment-1407675351) Please try adding `"browserNavigationTimeout": 300000,` to your config.yaml (https://github.com/alexbelgium/hassio-addons/issues/675#issuecomment-1407675351)
### Other errors ### Other errors

View File

@@ -86,5 +86,5 @@ schema:
slug: epicgamesfree slug: epicgamesfree
udev: true udev: true
url: https://github.com/alexbelgium/hassio-addons url: https://github.com/alexbelgium/hassio-addons
version: "debian-2025-11-19" version: "debian-2025-11-16"
webui: "[PROTO:ssl]://[HOST]:[PORT:3000]" webui: "[PROTO:ssl]://[HOST]:[PORT:3000]"

View File

@@ -7,22 +7,15 @@ set -e
############## ##############
HOME="/config/addons_config/epicgamesfree" HOME="/config/addons_config/epicgamesfree"
CONFIG_JSON="$HOME/config.json" if [ ! -f "$HOME"/config.json ]; then
LEGACY_YAML="$HOME/config.yaml"
if [ ! -f "$CONFIG_JSON" ]; then
if [ -f "$LEGACY_YAML" ]; then
bashio::log.warning "A legacy config.yaml was found. A default config.json will be created. Please migrate your settings to the new file format and restart the add-on"
fi
# Copy default config.json # Copy default config.json
cp /templates/config.json "$CONFIG_JSON" cp /templates/config.json "$HOME"/config.json
chmod 755 "$CONFIG_JSON" chmod 755 "$HOME"/config.json
bashio::log.warning "A default config.json file was copied in $HOME. Please customize according to https://github.com/claabs/epicgames-freegames-node#configuration and restart the add-on" bashio::log.warning "A default config.json file was copied in $HOME. Please customize according to https://github.com/claabs/epicgames-freegames-node#json-configuration and restart the add-on"
sleep 5 sleep 5
bashio::exit.nok bashio::exit.nok
else else
bashio::log.warning "The config.json file found in $HOME will be used. Please customize according to https://github.com/claabs/epicgames-freegames-node#configuration and restart the add-on" bashio::log.warning "The config.json file found in $HOME will be used. Please customize according to https://github.com/claabs/epicgames-freegames-node#json-configuration and restart the add-on"
fi fi
# Permissions # Permissions

View File

@@ -1,78 +0,0 @@
{
"runOnStartup":true,
"cronSchedule":"0 */6 * * *",
"logLevel":"info",
"webPortalConfig":{
"baseUrl":"https://epic.example.com"
},
"accounts":[
{
"email":"example@gmail.com"
}
],
"notifiers":[
{
"type":"email",
"smtpHost":"smtp.gmail.com",
"smtpPort":587,
"emailSenderAddress":"hello@gmail.com",
"emailSenderName":"Epic Games Captchas",
"emailRecipientAddress":"hello@gmail.com",
"secure":false,
"auth":{
"user":"hello@gmail.com",
"pass":"abc123"
}
},
{
"type":"discord",
"webhookUrl":"https://discord.com/api/webhooks/123456789123456789/A-abcdefghijklmn-abcdefghijklmnopqrst12345678-abcdefghijklmnop123456",
"mentionedUsers":[
"914360712086843432"
],
"mentionedRoles":[
"734548250895319070"
]
},
{
"type":"telegram",
"apiUrl":"https://api.telegram.org",
"token":"644739147:AAGMPo-Jz3mKRnHRTnrPEDi7jUF1vqNOD5k",
"chatId":"-987654321"
},
{
"type":"apprise",
"apiUrl":"http://192.168.1.2:8000",
"urls":"mailto://user:pass@gmail.com"
},
{
"type":"pushover",
"token":"a172fyyl9gw99p2xi16tq8hnib48p2",
"userKey":"uvgidym7l5ggpwu2r8i1oy6diaapll"
},
{
"type":"gotify",
"apiUrl":"https://gotify.net",
"token":"SnL-wAvmfo_QT"
},
{
"type":"homeassistant",
"instance":"https://homeassistant.example.com",
"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
"notifyservice":"mobile_app_smartphone_name"
},
{
"type":"bark",
"key":"xxxxxxxxxxxxxxxxxxxxxx",
"title":"epicgames-freegames",
"group":"epicgames-freegames",
"apiUrl":"https://api.day.app"
},
{
"type":"ntfy",
"webhookUrl":"https://ntfy.example.com/mytopic",
"priority":"urgent",
"token":"tk_mytoken"
}
]
}

View File

@@ -0,0 +1,50 @@
runOnStartup: true
cronSchedule: 0 */6 * * *
logLevel: info
webPortalConfig:
baseUrl: https://epic.example.com
accounts:
- email: example@gmail.com
notifiers:
- type: email
smtpHost: smtp.gmail.com
smtpPort: 587
emailSenderAddress: hello@gmail.com
emailSenderName: Epic Games Captchas
emailRecipientAddress: hello@gmail.com
secure: false
auth:
user: hello@gmail.com
pass: abc123
- type: discord
webhookUrl: https://discord.com/api/webhooks/123456789123456789/A-abcdefghijklmn-abcdefghijklmnopqrst12345678-abcdefghijklmnop123456
mentionedUsers:
- "914360712086843432"
mentionedRoles:
- "734548250895319070"
- type: telegram
apiUrl: https://api.telegram.org
token: 644739147:AAGMPo-Jz3mKRnHRTnrPEDi7jUF1vqNOD5k
chatId: "-987654321"
- type: apprise
apiUrl: http://192.168.1.2:8000
urls: mailto://user:pass@gmail.com
- type: pushover
token: a172fyyl9gw99p2xi16tq8hnib48p2
userKey: uvgidym7l5ggpwu2r8i1oy6diaapll
- type: gotify
apiUrl: https://gotify.net
token: SnL-wAvmfo_QT
- type: homeassistant
instance: https://homeassistant.example.com
token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
notifyservice: mobile_app_smartphone_name
- type: bark
key: xxxxxxxxxxxxxxxxxxxxxx
title: epicgames-freegames
group: epicgames-freegames
apiUrl: https://api.day.app
- type: ntfy
webhookUrl: https://ntfy.example.com/mytopic
priority: urgent
token: tk_mytoken

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -1,5 +1,3 @@
## 2.3.1-3 (23-11-2025)
- Minor bugs fixed
## 2.3.1-2 (22-11-2025) ## 2.3.1-2 (22-11-2025)
- Minor bugs fixed - Minor bugs fixed

View File

@@ -141,6 +141,6 @@ slug: immich
udev: true udev: true
url: https://github.com/alexbelgium/hassio-addons url: https://github.com/alexbelgium/hassio-addons
usb: true usb: true
version: 2.3.1-3 version: 2.3.1-2
video: true video: true
webui: http://[HOST]:[PORT:8080] webui: http://[HOST]:[PORT:8080]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -1,5 +1,3 @@
## 2.3.1-3 (23-11-2025)
- Minor bugs fixed
## 2.3.1-2 (22-11-2025) ## 2.3.1-2 (22-11-2025)
- Minor bugs fixed - Minor bugs fixed

View File

@@ -3,8 +3,7 @@ arch:
- amd64 - amd64
backup_exclude: backup_exclude:
- "**/machine-learning/*" - "**/machine-learning/*"
description: description: Self-hosted photo and video backup solution directly from your mobile phone
Self-hosted photo and video backup solution directly from your mobile phone
devices: devices:
- /dev/dri - /dev/dri
- /dev/dxg - /dev/dxg
@@ -140,6 +139,6 @@ slug: immich_noml
udev: true udev: true
url: https://github.com/alexbelgium/hassio-addons url: https://github.com/alexbelgium/hassio-addons
usb: true usb: true
version: 2.3.1-3 version: 2.3.1-2
video: true video: true
webui: http://[HOST]:[PORT:8080] webui: http://[HOST]:[PORT:8080]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -1,8 +1,3 @@
## breaking_versions: 10.11.3-1 (23-11-2025)
- Minor bugs fixed
## 10.11.3-1 (23-11-2025)
- Fix optional `i915_enable_guc` setting so the add-on no longer requires a value after updates.
## 10.11.3 (22-11-2025) ## 10.11.3 (22-11-2025)
- Update to latest version from linuxserver/docker-jellyfin (changelog : https://github.com/linuxserver/docker-jellyfin/releases) - Update to latest version from linuxserver/docker-jellyfin (changelog : https://github.com/linuxserver/docker-jellyfin/releases)

View File

@@ -91,6 +91,7 @@ options:
PGID: 0 PGID: 0
PUID: 0 PUID: 0
data_location: /share/jellyfin data_location: /share/jellyfin
i915_enable_guc: null
panel_admin: false panel_admin: false
panel_icon: mdi:billiards-rack panel_icon: mdi:billiards-rack
ports: ports:
@@ -125,5 +126,5 @@ schema:
slug: jellyfin slug: jellyfin
udev: true udev: true
url: https://github.com/alexbelgium/hassio-addons url: https://github.com/alexbelgium/hassio-addons
version: "10.11.3-1" version: "10.11.3"
video: true video: true

0
jellyfin/rootfs/etc/services.d/nginx/run Normal file → Executable file
View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -166,7 +166,7 @@ if [[ "${MEILISEARCH_LOCAL}" == true ]]; then
bashio::log.error "${message}" bashio::log.error "${message}"
if [ -n "${S6_SVSCANCTL_BIN}" ]; then if [ -n "${S6_SVSCANCTL_BIN}" ]; then
if ! "${S6_SVSCANCTL_BIN}" -t "${S6_SUPERVISED_DIR}" 2>/dev/null; then if ! "${S6_SVSCANCTL_BIN}" -t "${S6_SUPERVISED_DIR}" 2> /dev/null; then
bashio::log.error "Unable to signal s6-svscanctl to stop services" bashio::log.error "Unable to signal s6-svscanctl to stop services"
fi fi
else else
@@ -181,7 +181,7 @@ if [[ "${MEILISEARCH_LOCAL}" == true ]]; then
} }
meilisearch_ensure_running() { meilisearch_ensure_running() {
if kill -0 "${MEILISEARCH_PID}" 2>/dev/null; then if kill -0 "${MEILISEARCH_PID}" 2> /dev/null; then
return 0 return 0
fi fi
@@ -201,11 +201,11 @@ if [[ "${MEILISEARCH_LOCAL}" == true ]]; then
} }
MEILISEARCH_CMD=( MEILISEARCH_CMD=(
env \ env
MEILI_ENV="${MEILISEARCH_ENVIRONMENT}" \ MEILI_ENV="${MEILISEARCH_ENVIRONMENT}"
MEILI_NO_ANALYTICS="${MEILISEARCH_NO_ANALYTICS}" \ MEILI_NO_ANALYTICS="${MEILISEARCH_NO_ANALYTICS}"
meilisearch \ meilisearch
--http-addr "${MEILISEARCH_ADDR}" \ --http-addr "${MEILISEARCH_ADDR}"
--db-path "${MEILISEARCH_DB_PATH}" --db-path "${MEILISEARCH_DB_PATH}"
) )
@@ -218,7 +218,7 @@ if [[ "${MEILISEARCH_LOCAL}" == true ]]; then
bashio::log.info "Waiting for Meilisearch TCP socket" bashio::log.info "Waiting for Meilisearch TCP socket"
for attempt in $(seq 1 30); do for attempt in $(seq 1 30); do
if bash -c "cat < /dev/null > /dev/tcp/${MEILISEARCH_HOST}/${MEILISEARCH_PORT}" 2>/dev/null; then if bash -c "cat < /dev/null > /dev/tcp/${MEILISEARCH_HOST}/${MEILISEARCH_PORT}" 2> /dev/null; then
break break
fi fi

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

0
nzbget/rootfs/etc/services.d/nginx/run Normal file → Executable file
View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@@ -1,6 +1,3 @@
## 5.1.2-19 (24-11-2025)
- Cycle through ip providers to avoid rate limiting api
## 5.1.2-13 (19-11-2025) ## 5.1.2-13 (19-11-2025)
- Add IPv4 fallback for WireGuard connections - Add IPv4 fallback for WireGuard connections

View File

@@ -145,4 +145,4 @@ schema:
slug: qbittorrent slug: qbittorrent
udev: true udev: true
url: https://github.com/alexbelgium/hassio-addons url: https://github.com/alexbelgium/hassio-addons
version: 5.1.2-19 version: 5.1.2-13

View File

@@ -14,6 +14,9 @@ if bashio::config.true 'openvpn_enabled'; then
bashio::log.info "Openvpn enabled, configuring" bashio::log.info "Openvpn enabled, configuring"
bashio::log.info "----------------------------" bashio::log.info "----------------------------"
# Get current ip
curl -s ipecho.net/plain > /currentip
# Function to check for files path # Function to check for files path
function check_path() { function check_path() {

View File

@@ -50,7 +50,7 @@ if [ -z "${wireguard_config:-}" ]; then
fi fi
fi fi
dos2unix "${wireguard_config}" >/dev/null 2>&1 || true dos2unix "${wireguard_config}" > /dev/null 2>&1 || true
interface_name="$(basename "${wireguard_config}" .conf)" interface_name="$(basename "${wireguard_config}" .conf)"
if [[ -z "${interface_name}" ]]; then if [[ -z "${interface_name}" ]]; then
@@ -60,7 +60,7 @@ fi
wireguard_runtime_config="${WIREGUARD_STATE_DIR}/${interface_name}.conf" wireguard_runtime_config="${WIREGUARD_STATE_DIR}/${interface_name}.conf"
cp "${wireguard_config}" "${wireguard_runtime_config}" cp "${wireguard_config}" "${wireguard_runtime_config}"
chmod 600 "${wireguard_runtime_config}" 2>/dev/null || true chmod 600 "${wireguard_runtime_config}" 2> /dev/null || true
bashio::log.info 'Prepared WireGuard runtime configuration for initial connection attempt.' bashio::log.info 'Prepared WireGuard runtime configuration for initial connection attempt.'
echo "${wireguard_runtime_config}" > "${WIREGUARD_STATE_DIR}/config" echo "${wireguard_runtime_config}" > "${WIREGUARD_STATE_DIR}/config"
@@ -76,4 +76,7 @@ else
bashio::log.warning "qBittorrent config file not found. Bind the client manually to interface ${interface_name}." bashio::log.warning "qBittorrent config file not found. Bind the client manually to interface ${interface_name}."
fi fi
# Get current ip
curl -s ipecho.net/plain > /currentip
bashio::log.info "WireGuard prepared with interface ${interface_name} using configuration ${wireguard_config##*/}." bashio::log.info "WireGuard prepared with interface ${interface_name} using configuration ${wireguard_config##*/}."

View File

@@ -2,241 +2,14 @@
# shellcheck shell=bash # shellcheck shell=bash
WEBUI_PORT=${WEBUI_PORT:-8080} WEBUI_PORT=${WEBUI_PORT:-8080}
export PATH="/usr/local/sbin:/usr/local/bin:${PATH}"
# --- Configuration & Pre-checks --- export PATH="/usr/local/sbin:/usr/local/bin:${PATH}"
if bashio::config.true 'silent'; then if bashio::config.true 'silent'; then
sed -i 's|/proc/1/fd/1 hassio;|off;|g' /etc/nginx/nginx.conf sed -i 's|/proc/1/fd/1 hassio;|off;|g' /etc/nginx/nginx.conf
fi fi
# --- Helper Functions ---
_fetch_public_ip() {
local resp
local url
local urls=(
"https://icanhazip.com"
"https://ifconfig.me/ip"
"https://api64.ipify.org"
"https://checkip.amazonaws.com"
"https://domains.google.com/checkip"
"https://ipinfo.io/ip"
)
local shuffled_urls
mapfile -t shuffled_urls < <(printf "%s\n" "${urls[@]}" | shuf)
# Loop through the now-randomized list
for url in "${shuffled_urls[@]}"; do
resp=$(curl -fsS --max-time 5 "${url}" 2>/dev/null || true)
resp="${resp//[[:space:]]/}"
# Validate IPv4 or IPv6
if [[ "${resp}" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] || [[ "${resp}" =~ ^[0-9a-fA-F:]+$ ]]; then
printf '%s\n' "${resp}"
return 0
fi
done
return 1
}
_fetch_country_code() {
local resp
local url
local urls=(
"https://ipapi.co/country/"
"http://ip-api.com/line/?fields=countryCode"
"https://ipinfo.io/country"
)
local shuffled_urls_output
shuffled_urls_output=$(printf '%s\n' "${urls[@]}" | shuf)
while IFS= read -r url; do
# Skip empty lines if any
[[ -z "${url}" ]] && continue
# Fetch the response with a 5-second timeout
resp=$(curl -fsS --max-time 5 "${url}" 2>/dev/null || true)
# Clean whitespace/newlines
resp="${resp//[[:space:]]/}"
# Validation: Ensure the response is exactly 2 letters (ISO 3166-1 alpha-2)
if [[ "${resp}" =~ ^[A-Za-z]{2}$ ]]; then
# Convert to uppercase and print
printf '%s\n' "${resp^^}"
return 0
fi
done <<< "${shuffled_urls_output}" # Process the shuffled output
return 1
}
_vpn_monitor_public_ip() {
local vpn_label="${1:-VPN}"
local current_ip_file="/currentip"
local baseline_ip vpn_ip country
local interval=${VPN_LEAK_CHECK_INTERVAL:-300}
local initial_delay=${VPN_LEAK_INITIAL_DELAY:-60}
# Pre-flight checks
if ! command -v curl >/dev/null 2>&1; then
bashio::log.warning "${vpn_label}: curl not found; VPN leak monitoring disabled."
return 0
fi
if [[ ! -s "${current_ip_file}" ]]; then
bashio::log.warning "${vpn_label}: public ip could not be reached; VPN leak monitoring disabled."
return 0
fi
if ! bashio::fs.file_exists "${current_ip_file}"; then
bashio::log.warning "${vpn_label}: baseline IP file ${current_ip_file} not found; VPN leak monitoring disabled."
return 0
fi
baseline_ip="$(tr -d '[:space:]' < "${current_ip_file}")"
if [[ -z "${baseline_ip}" ]]; then
bashio::log.warning "${vpn_label}: baseline IP in ${current_ip_file} is empty; VPN leak monitoring disabled."
return 0
fi
bashio::log.debug "${vpn_label}: Waiting ${initial_delay}s before first leak check."
sleep "${initial_delay}"
while true; do
vpn_ip="$(_fetch_public_ip || true)"
if [[ -z "${vpn_ip}" ]]; then
bashio::log.warning "${vpn_label}: Failed to fetch public IP (rate limited or connection down)."
else
if country="$(_fetch_country_code || true)"; then
bashio::log.info "${vpn_label}: Current IP: ${vpn_ip} (${country})"
else
bashio::log.info "${vpn_label}: Current IP: ${vpn_ip} (Country Unknown)"
fi
# LEAK DETECTED
if [[ "${vpn_ip}" == "${baseline_ip}" ]]; then
bashio::log.fatal "${vpn_label}: VPN LEAK DETECTED! Current IP ${vpn_ip} matches baseline. Stopping container."
s6-svscanctl -t /var/run/s6/services 2>/dev/null || true
exit 1
fi
fi
sleep "${interval}"
done
}
# --- WireGuard Specific Logic ---
_setup_wireguard() {
local WIREGUARD_STATE_DIR="/var/run/wireguard"
local output=""
local status=0
if ! bashio::fs.file_exists "${WIREGUARD_STATE_DIR}/config"; then
bashio::exit.nok 'WireGuard runtime configuration not prepared. Please restart the add-on.'
fi
local wireguard_config
wireguard_config="$(cat "${WIREGUARD_STATE_DIR}/config")"
local wireguard_interface
wireguard_interface="$(cat "${WIREGUARD_STATE_DIR}/interface" 2>/dev/null || echo 'wg0')"
if ip link show "${wireguard_interface}" >/dev/null 2>&1; then
bashio::log.warning "WireGuard interface ${wireguard_interface} already exists. Resetting."
wg-quick down "${wireguard_config}" >/dev/null 2>&1 || true
fi
bashio::log.info "Starting WireGuard interface ${wireguard_interface}..."
# Internal helper: fallback for iptables-legacy
_wg_prepare_legacy() {
local legacy_bin_dir="${WIREGUARD_STATE_DIR}/iptables-legacy-bin"
mkdir -p "${legacy_bin_dir}"
local cmd
for cmd in iptables iptables-save iptables-restore ip6tables ip6tables-save ip6tables-restore; do
if command -v "${cmd}-legacy" >/dev/null 2>&1; then
ln -sf "$(command -v "${cmd}-legacy")" "${legacy_bin_dir}/${cmd}"
fi
done
chmod 700 "${legacy_bin_dir}" 2>/dev/null || true
export PATH="${legacy_bin_dir}:${PATH}"
bashio::log.warning 'Retrying WireGuard using iptables-legacy wrappers.'
}
# Internal helper: Attempt connection
_wg_up_attempt() {
local config_path="$1"
output="$(wg-quick up "${config_path}" 2>&1)" || status=$?
if [ "${status}" -eq 0 ]; then return 0; fi
# Check for iptables errors and try legacy fallback
if echo "${output}" | grep -qiE 'iptables-restore|ip6tables-restore|xtables'; then
if command -v iptables-legacy >/dev/null 2>&1; then
wg-quick down "${config_path}" >/dev/null 2>&1 || true
_wg_prepare_legacy
output="$(wg-quick up "${config_path}" 2>&1)" || status=$?
else
bashio::log.warning 'iptables errors detected but iptables-legacy missing.'
status=1
fi
fi
return "${status}"
}
# 1. First Attempt
if ! _wg_up_attempt "${wireguard_config}"; then
bashio::log.warning 'Initial WireGuard connection failed. Trying IPv4-only endpoints.'
bashio::log.debug "Output: ${output}"
# 2. IPv4 Fallback Preparation
local ipv4_config="${WIREGUARD_STATE_DIR}/${wireguard_interface}-ipv4.conf"
: > "${ipv4_config}"
chmod 600 "${ipv4_config}" 2>/dev/null || true
local line endpoint endpoint_host endpoint_port
while IFS= read -r line || [ -n "$line" ]; do
if [[ "${line}" =~ ^Endpoint ]]; then
endpoint="${line#Endpoint = }"
endpoint_host="${endpoint%:*}"
endpoint_port="${endpoint##*:}"
# Resolve hostname to IPv4
mapfile -t ipv4_candidates < <(getent ahostsv4 "${endpoint_host}" | awk '{print $1}' | uniq)
if [ ${#ipv4_candidates[@]} -gt 0 ]; then
bashio::log.debug "Resolved ${endpoint_host} to ${ipv4_candidates[0]}"
echo "Endpoint = ${ipv4_candidates[0]}:${endpoint_port}" >> "${ipv4_config}"
else
echo "${line}" >> "${ipv4_config}"
fi
else
echo "${line}" >> "${ipv4_config}"
fi
done < "${wireguard_config}"
wg-quick down "${wireguard_config}" >/dev/null 2>&1 || true
# 3. Second Attempt (IPv4 only)
if ! _wg_up_attempt "${ipv4_config}"; then
bashio::log.error 'WireGuard failed to establish connection.'
bashio::log.error "${output}"
bashio::exit.nok 'WireGuard start failed.'
fi
fi
bashio::log.info "WireGuard interface ${wireguard_interface} is up."
# DNS Refresh
if command -v resolvconf >/dev/null 2>&1; then
resolvconf -u >/dev/null 2>&1 || bashio::log.warning 'resolvconf -u failed.'
fi
}
# --- Main Execution ---
echo "$(_fetch_public_ip || true)" > /currentip
if bashio::config.true 'openvpn_enabled'; then if bashio::config.true 'openvpn_enabled'; then
# Start Leak Monitor
_vpn_monitor_public_ip "OpenVPN" &
exec /usr/sbin/openvpn \ exec /usr/sbin/openvpn \
--config /config/openvpn/config.ovpn \ --config /config/openvpn/config.ovpn \
--script-security 2 \ --script-security 2 \
@@ -246,29 +19,133 @@ if bashio::config.true 'openvpn_enabled'; then
--pull-filter ignore "ifconfig-ipv6" \ --pull-filter ignore "ifconfig-ipv6" \
--pull-filter ignore "tun-ipv6" \ --pull-filter ignore "tun-ipv6" \
--pull-filter ignore "redirect-gateway ipv6" \ --pull-filter ignore "redirect-gateway ipv6" \
--pull-filter ignore "dhcp-option DNS6" \ --pull-filter ignore "dhcp-option DNS6"
& else
if bashio::config.true 'wireguard_enabled'; then
WIREGUARD_STATE_DIR="/var/run/wireguard"
elif bashio::config.true 'wireguard_enabled'; then if ! bashio::fs.file_exists "${WIREGUARD_STATE_DIR}/config"; then
bashio::exit.nok 'WireGuard runtime configuration not prepared. Please restart the add-on.'
fi
# Run modularized WireGuard setup wireguard_config="$(cat "${WIREGUARD_STATE_DIR}/config")"
_setup_wireguard wireguard_interface="$(cat "${WIREGUARD_STATE_DIR}/interface" 2> /dev/null || echo 'wg0')"
# Start Leak Monitor if ip link show "${wireguard_interface}" &> /dev/null; then
_vpn_monitor_public_ip "WireGuard" & bashio::log.warning "WireGuard interface ${wireguard_interface} already exists. Attempting to reset it."
wg-quick down "${wireguard_config}" > /dev/null 2>&1 || true
fi
fi bashio::log.info "Starting WireGuard interface ${wireguard_interface} using ${wireguard_config##*/}."
# --- Launch qBittorrent --- # Prefer host-provided iptables-legacy binaries if the default backend fails.
_wireguard_prepare_iptables_legacy() {
local legacy_bin_dir="${WIREGUARD_STATE_DIR}/iptables-legacy-bin"
mkdir -p "${legacy_bin_dir}"
# Determine log output based on silent mode for cmd in iptables iptables-save iptables-restore ip6tables ip6tables-save ip6tables-restore; do
QB_OUTPUT="/dev/stdout" if command -v "${cmd}-legacy" > /dev/null 2>&1; then
if bashio::config.true 'silent'; then ln -sf "$(command -v "${cmd}-legacy")" "${legacy_bin_dir}/${cmd}"
QB_OUTPUT="/dev/null" fi
fi done
bashio::log.info "Starting qBittorrent..." chmod 700 "${legacy_bin_dir}" 2> /dev/null || true
export PATH="${legacy_bin_dir}:${PATH}"
bashio::log.warning 'Retrying WireGuard bring-up using iptables-legacy wrappers.'
}
exec \ _wireguard_up_with_iptables_fallback() {
local config_path="$1"
local status
output=""
output=$(wg-quick up "${config_path}" 2>&1)
status=$?
if [ "$status" -eq 0 ]; then
return 0
fi
if echo "${output}" | grep -qiE 'iptables-restore|ip6tables-restore|xtables'; then
if command -v iptables-legacy > /dev/null 2>&1 || command -v ip6tables-legacy > /dev/null 2>&1; then
wg-quick down "${config_path}" > /dev/null 2>&1 || true
_wireguard_prepare_iptables_legacy
output=$(wg-quick up "${config_path}" 2>&1)
status=$?
else
bashio::log.warning 'iptables errors detected but iptables-legacy binaries are unavailable in the image.'
status=1
fi
fi
return "${status}"
}
if ! _wireguard_up_with_iptables_fallback "${wireguard_config}"; then
bashio::log.warning 'Initial WireGuard connection attempt failed. Trying again with IPv4-only endpoints.'
bashio::log.warning "First attempt output:${bashio::constants.LF}${output}"
ipv4_config="${WIREGUARD_STATE_DIR}/${wireguard_interface}-ipv4.conf"
echo -n > "${ipv4_config}"
chmod 600 "${ipv4_config}" 2> /dev/null || true
while IFS= read -r line; do
if [[ "${line}" =~ ^Endpoint ]]; then
endpoint="${line#Endpoint = }"
endpoint_host="${endpoint%:*}"
endpoint_port="${endpoint##*:}"
mapfile -t ipv4_candidates < <(getent ahostsv4 "${endpoint_host}" | awk '{print $1}' | uniq)
if [ ${#ipv4_candidates[@]} -gt 0 ]; then
bashio::log.debug "Resolved ${endpoint_host} to IPv4 address ${ipv4_candidates[0]} for WireGuard fallback."
echo "Endpoint = ${ipv4_candidates[0]}:${endpoint_port}" >> "${ipv4_config}"
else
bashio::log.warning "No IPv4 address found for ${endpoint_host}. Keeping original endpoint for fallback."
echo "${line}" >> "${ipv4_config}"
fi
else
echo "${line}" >> "${ipv4_config}"
fi
done < "${wireguard_config}"
wg-quick down "${wireguard_config}" > /dev/null 2>&1 || true
if ! _wireguard_up_with_iptables_fallback "${ipv4_config}"; then
bashio::log.error 'WireGuard failed to establish a connection after IPv4-only retry.'
bashio::log.error "wg-quick output:"
bashio::log.error "${output}"
bashio::log.error 'Troubleshooting steps:'
bashio::log.error " 1. Confirm that the WireGuard configuration file '${wireguard_config}' exists inside the container and contains valid private/public keys, endpoint and AllowedIPs."
bashio::log.error ' 2. Ensure UDP port 51820 (or the port defined in your config) is forwarded on your router to this host and not blocked by your firewall or ISP.'
bashio::log.error ' 3. Verify that the configured endpoint (IP/hostname and port) is reachable from this container (e.g. ping or nc from a debug shell).'
bashio::log.error ' 4. Check that the system time is correct (NTP); large time drift can break key handshakes.'
bashio::log.error ' 5. Confirm that WireGuard kernel support / module is available in the host system.'
bashio::log.error ' 6. If DNS names are used for the endpoint, verify DNS resolution from inside the container (e.g. nslookup or dig).'
bashio::exit.nok 'WireGuard start failed. See the log above for details.'
fi
fi
bashio::log.info "WireGuard interface ${wireguard_interface} is up."
# Refresh DNS resolver configuration if resolvconf is present
if command -v resolvconf > /dev/null 2>&1; then
bashio::log.info 'Refreshing DNS resolver configuration via resolvconf -u.'
if ! resolvconf -u > /dev/null 2>&1; then
bashio::log.warning 'resolvconf -u failed. DNS configuration may not have been updated.'
fi
else
bashio::log.debug 'resolvconf not found in PATH; skipping DNS refresh.'
fi
fi
if bashio::config.true 'silent'; then
exec \
s6-notifyoncheck -d -n 300 -w 1000 -c "nc -z localhost ${WEBUI_PORT}" \ s6-notifyoncheck -d -n 300 -w 1000 -c "nc -z localhost ${WEBUI_PORT}" \
s6-setuidgid abc /usr/bin/qbittorrent-nox --webui-port="${WEBUI_PORT}" > "${QB_OUTPUT}" s6-setuidgid abc /usr/bin/qbittorrent-nox --webui-port="${WEBUI_PORT}" > /dev/null
else
exec \
s6-notifyoncheck -d -n 300 -w 1000 -c "nc -z localhost ${WEBUI_PORT}" \
s6-setuidgid abc /usr/bin/qbittorrent-nox --webui-port="${WEBUI_PORT}"
fi
fi

8
qbittorrent/rootfs/etc/services.d/nginx/run Normal file → Executable file
View File

@@ -38,7 +38,7 @@ get_ip_info() {
# Outputs: "<ip> <country>" on success # Outputs: "<ip> <country>" on success
local json ip country local json ip country
if ! json="$(curl -fsS --max-time 10 "${VPN_INFO_URL}" 2>/dev/null)"; then if ! json="$(curl -fsS --max-time 10 "${VPN_INFO_URL}" 2> /dev/null)"; then
bashio::log.warning "Unable to reach VPN info service at ${VPN_INFO_URL}." bashio::log.warning "Unable to reach VPN info service at ${VPN_INFO_URL}."
return 1 return 1
fi fi
@@ -173,7 +173,7 @@ trap '
# Monitoring loop # Monitoring loop
while true; do while true; do
# If nginx died, stop this service and let s6 handle restart policy # If nginx died, stop this service and let s6 handle restart policy
if ! kill -0 "${nginx_pid}" 2>/dev/null; then if ! kill -0 "${nginx_pid}" 2> /dev/null; then
bashio::log.error "nginx process exited unexpectedly; leaving service." bashio::log.error "nginx process exited unexpectedly; leaving service."
exit 1 exit 1
fi fi
@@ -193,8 +193,8 @@ while true; do
if [[ -n "${REAL_IP}" ]] && [[ "${current_ip}" == "${REAL_IP}" ]]; then if [[ -n "${REAL_IP}" ]] && [[ "${current_ip}" == "${REAL_IP}" ]]; then
bashio::log.error "IP LEAK DETECTED: current external IP ${current_ip} matches real IP ${REAL_IP}." bashio::log.error "IP LEAK DETECTED: current external IP ${current_ip} matches real IP ${REAL_IP}."
bashio::log.error "Stopping nginx and exiting so the supervisor can restart the add-on." bashio::log.error "Stopping nginx and exiting so the supervisor can restart the add-on."
kill "${nginx_pid}" 2>/dev/null || true kill "${nginx_pid}" 2> /dev/null || true
wait "${nginx_pid}" 2>/dev/null || true wait "${nginx_pid}" 2> /dev/null || true
exit 1 exit 1
fi fi
done done

0
qbittorrent/rootfs/etc/services.d/timer/run Normal file → Executable file
View File

View File

@@ -15,7 +15,7 @@ shift || true
restore_backup() { restore_backup() {
if [ -f "${BACKUP_FILE}" ]; then if [ -f "${BACKUP_FILE}" ]; then
cat "${BACKUP_FILE}" > /etc/resolv.conf cat "${BACKUP_FILE}" >/etc/resolv.conf
fi fi
} }
@@ -26,10 +26,10 @@ apply_dns() {
# Skip optional arguments such as -m <metric> or -x # Skip optional arguments such as -m <metric> or -x
while [ "$#" -gt 0 ]; do while [ "$#" -gt 0 ]; do
case "$1" in case "$1" in
-m|-p|-w) -m | -p | -w)
shift 2 || true shift 2 || true
;; ;;
-x|-y|-Z) -x | -y | -Z)
shift 1 || true shift 1 || true
;; ;;
--) --)
@@ -43,7 +43,7 @@ apply_dns() {
done done
tmp_file="${STATE_DIR}/${iface}.conf" tmp_file="${STATE_DIR}/${iface}.conf"
cat > "${tmp_file}" cat >"${tmp_file}"
if [ ! -f "${BACKUP_FILE}" ]; then if [ ! -f "${BACKUP_FILE}" ]; then
cp /etc/resolv.conf "${BACKUP_FILE}" 2>/dev/null || true cp /etc/resolv.conf "${BACKUP_FILE}" 2>/dev/null || true
@@ -52,34 +52,34 @@ apply_dns() {
{ {
echo "# Generated by WireGuard add-on resolvconf shim" echo "# Generated by WireGuard add-on resolvconf shim"
cat "${tmp_file}" cat "${tmp_file}"
} > /etc/resolv.conf } >/etc/resolv.conf
} }
case "${command}" in case "${command}" in
-a) -a)
if [ "$#" -eq 0 ]; then if [ "$#" -eq 0 ]; then
exit 0 exit 0
fi fi
apply_dns "$@" apply_dns "$@"
;; ;;
-d) -d)
if [ "$#" -gt 0 ]; then if [ "$#" -gt 0 ]; then
rm -f "${STATE_DIR}/$1.conf" rm -f "${STATE_DIR}/$1.conf"
fi fi
restore_backup restore_backup
;; ;;
-u) -u)
latest_conf="$(find "${STATE_DIR}" -maxdepth 1 -type f -name '*.conf' -print | head -n 1 || true)" latest_conf="$(find "${STATE_DIR}" -maxdepth 1 -type f -name '*.conf' -print | head -n 1 || true)"
if [ -n "${latest_conf}" ] && [ -f "${latest_conf}" ]; then if [ -n "${latest_conf}" ] && [ -f "${latest_conf}" ]; then
{ {
echo "# Generated by WireGuard add-on resolvconf shim" echo "# Generated by WireGuard add-on resolvconf shim"
cat "${latest_conf}" cat "${latest_conf}"
} > /etc/resolv.conf } >/etc/resolv.conf
else else
restore_backup restore_backup
fi fi
;; ;;
*) *)
# Treat other commands as successful no-ops to remain compatible with wg-quick. # Treat other commands as successful no-ops to remain compatible with wg-quick.
exit 0 exit 0
;; ;;

View File

@@ -13,7 +13,7 @@ cleanup() {
trap cleanup EXIT trap cleanup EXIT
RULES_FILE="$(mktemp)" RULES_FILE="$(mktemp)"
cat > "${RULES_FILE}" cat >"${RULES_FILE}"
ipv6_unavailable() { ipv6_unavailable() {
local message="$1" local message="$1"
@@ -26,7 +26,7 @@ ipv6_unavailable() {
# First attempt with the original ruleset # First attempt with the original ruleset
output="" output=""
if output="$(${REAL_IP6TABLES_RESTORE} "$@" < "${RULES_FILE}" 2>&1)"; then if output="$(${REAL_IP6TABLES_RESTORE} "$@" <"${RULES_FILE}" 2>&1)"; then
[[ -n "${output}" ]] && printf '%s\n' "${output}" >&2 [[ -n "${output}" ]] && printf '%s\n' "${output}" >&2
exit 0 exit 0
fi fi
@@ -34,10 +34,10 @@ status=$?
# Retry without comment matches if the kernel is missing the comment module # Retry without comment matches if the kernel is missing the comment module
SANITIZED_FILE="$(mktemp)" SANITIZED_FILE="$(mktemp)"
sed -E 's/-m[[:space:]]+comment[[:space:]]+--comment[[:space:]]+"[^"]*"//g' "${RULES_FILE}" > "${SANITIZED_FILE}" sed -E 's/-m[[:space:]]+comment[[:space:]]+--comment[[:space:]]+"[^"]*"//g' "${RULES_FILE}" >"${SANITIZED_FILE}"
retry_output="" retry_output=""
if retry_output="$(${REAL_IP6TABLES_RESTORE} "$@" < "${SANITIZED_FILE}" 2>&1)"; then if retry_output="$(${REAL_IP6TABLES_RESTORE} "$@" <"${SANITIZED_FILE}" 2>&1)"; then
printf '%s\n' "ip6tables-restore failed with comment matches; reapplied without comments." >&2 printf '%s\n' "ip6tables-restore failed with comment matches; reapplied without comments." >&2
printf '%s\n' "Original error: ${output}" >&2 printf '%s\n' "Original error: ${output}" >&2
[[ -n "${retry_output}" ]] && printf '%s\n' "${retry_output}" >&2 [[ -n "${retry_output}" ]] && printf '%s\n' "${retry_output}" >&2
@@ -49,7 +49,7 @@ retry_status=$?
legacy_output="" legacy_output=""
for legacy in /sbin/ip6tables-restore-legacy /usr/sbin/ip6tables-restore-legacy; do for legacy in /sbin/ip6tables-restore-legacy /usr/sbin/ip6tables-restore-legacy; do
if [[ -x "${legacy}" ]]; then if [[ -x "${legacy}" ]]; then
if legacy_output="$(${legacy} "$@" < "${RULES_FILE}" 2>&1)"; then if legacy_output="$(${legacy} "$@" <"${RULES_FILE}" 2>&1)"; then
printf '%s\n' "ip6tables-restore failed; succeeded using legacy backend." >&2 printf '%s\n' "ip6tables-restore failed; succeeded using legacy backend." >&2
printf '%s\n' "Original error: ${output}" >&2 printf '%s\n' "Original error: ${output}" >&2
[[ -n "${legacy_output}" ]] && printf '%s\n' "${legacy_output}" >&2 [[ -n "${legacy_output}" ]] && printf '%s\n' "${legacy_output}" >&2

Some files were not shown because too many files have changed in this diff Show More