Compare commits

..

No commits in common. "c23ad910df03e0768068177dbae22f1363ba3f4d" and "fb668bf3e2d20f941fcc2de81a6653a4b0b7559b" have entirely different histories.

13 changed files with 86 additions and 378 deletions

8
.idea/.gitignore vendored
View file

@ -1,8 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View file

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PublishConfigData" remoteFilesAllowedToDisappearOnAutoupload="false">
<serverData>
<paths name="//TOWER">
<serverdata>
<mappings>
<mapping local="$PROJECT_DIR$" web="/" />
</mappings>
</serverdata>
</paths>
</serverData>
</component>
</project>

View file

@ -1,6 +0,0 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

View file

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (2)" project-jdk-type="Python SDK" />
</project>

View file

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/prometheus-immich-exporter.iml" filepath="$PROJECT_DIR$/.idea/prometheus-immich-exporter.iml" />
</modules>
</component>
</project>

View file

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 3.10 (2)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View file

@ -14,7 +14,7 @@ RUN pip3 install .
ENV IMMICH_API_TOKEN="" ENV IMMICH_API_TOKEN=""
ENV IMMICH_HOST="" ENV IMMICH_HOST=""
ENV IMMICH_PORT="8080" ENV IMMICH_PORT=""
#has to be EXPORT_PORT 8000 or else it does not work, same applies to the env file #has to be EXPORT_PORT 8000 or else it does not work, same applies to the env file
ENV EXPORTER_PORT="8000" ENV EXPORTER_PORT="8000"
ENV EXPORTER_LOG_LEVEL="INFO" ENV EXPORTER_LOG_LEVEL="INFO"

View file

@ -5,14 +5,26 @@ A prometheus exporter for Immich. Get metrics from a server and offers them in a
## How to use it ## How to use it
Here is an example docker run command You can install this exporter with the following command:
```bash
pip3 install prometheus-qbittorrent-exporter
```
Then you can run it with
``` ```
docker run -e IMMICH_PORT=8080 -e IMMICH_HOST=192.168.178.1 -e IMMICH_API_TOKEN=TOKEN -p 8000:8000 friendlyfriend/prometheus-immich-exporter immich-exporter
```
Another option is to run it in a docker container. Here is an example docker run command
```
docker run -e IMMICH_PORT=8010 -e IMMICH_HOST=192.168.178.1 -p 8000:8000 friendlyfriend/prometheus-immich-exporter
``` ```
Add this to your prometheus.yml Add this to your prometheus.yml
``` ```
- job_name: "Immich_exporter" - job_name: "immich_exporter"
static_configs: static_configs:
- targets: ['yourimmichexporter:port'] - targets: ['yourimmichexporter:port']
``` ```
@ -20,9 +32,8 @@ The application reads configuration using environment variables:
| Environment variable | Default | Description | | Environment variable | Default | Description |
|----------------------|----------|----------------------------------------------------| |----------------------|----------|----------------------------------------------------|
| `IMMICH_HOST` | | Immich proxy url | | `IMMICH_HOST` | | immich server hostname |
| `IMMICH_PORT` | `8080` | Immich proxy port | | `IMMICH_PORT` | | immich server port |
| `IMMICH_API_TOKEN` | | Immich API token, created from Immich dashboard |
| `EXPORTER_PORT` | `8000` | Exporter listening port | | `EXPORTER_PORT` | `8000` | Exporter listening port |
| `EXPORTER_LOG_LEVEL` | `INFO` | Log level. One of: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL` | | `EXPORTER_LOG_LEVEL` | `INFO` | Log level. One of: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL` |
| `METRICS_PREFIX` | `immich` | Prefix to add to all the metrics | | `METRICS_PREFIX` | `immich` | Prefix to add to all the metrics |

View file

@ -199,7 +199,7 @@
"refId": "A" "refId": "A"
} }
], ],
"title": "User count", "title": "user count",
"type": "stat" "type": "stat"
}, },
{ {
@ -261,7 +261,7 @@
"refId": "A" "refId": "A"
} }
], ],
"title": "Disk space used by Immich", "title": "disk space used by Immich",
"type": "stat" "type": "stat"
}, },
{ {
@ -323,7 +323,7 @@
"refId": "A" "refId": "A"
} }
], ],
"title": "Total disk size", "title": "total disk size",
"type": "stat" "type": "stat"
}, },
{ {
@ -385,7 +385,7 @@
"refId": "A" "refId": "A"
} }
], ],
"title": "Total disk size usage", "title": "total disk size usage",
"type": "stat" "type": "stat"
}, },
{ {
@ -451,7 +451,7 @@
"refId": "A" "refId": "A"
} }
], ],
"title": "Remaining disk size", "title": "remaining disk size",
"type": "stat" "type": "stat"
}, },
{ {
@ -484,7 +484,7 @@
"x": 0, "x": 0,
"y": 3 "y": 3
}, },
"hideTimeOverride": false, "hideTimeOverride": true,
"id": 24, "id": 24,
"options": { "options": {
"colorMode": "background", "colorMode": "background",
@ -509,7 +509,7 @@
}, },
"editorMode": "code", "editorMode": "code",
"exemplar": false, "exemplar": false,
"expr": "increase(immich_server_stats_usage_growth[1d])", "expr": "increase(immich_server_stats_usage_growth[24h])",
"instant": false, "instant": false,
"legendFormat": "__auto", "legendFormat": "__auto",
"range": true, "range": true,
@ -550,7 +550,7 @@
"x": 6, "x": 6,
"y": 3 "y": 3
}, },
"hideTimeOverride": false, "hideTimeOverride": true,
"id": 26, "id": 26,
"options": { "options": {
"colorMode": "background", "colorMode": "background",
@ -574,13 +574,13 @@
"uid": "${DS_PROMETHEUS}" "uid": "${DS_PROMETHEUS}"
}, },
"editorMode": "code", "editorMode": "code",
"expr": "increase(immich_server_stats_usage_growth[1w])", "expr": "increase(immich_server_stats_useage_growth[7d])",
"legendFormat": "__auto", "legendFormat": "__auto",
"range": true, "range": true,
"refId": "A" "refId": "A"
} }
], ],
"timeFrom": "1w", "timeFrom": "now/w",
"title": "Weekly data growth", "title": "Weekly data growth",
"type": "stat" "type": "stat"
}, },
@ -648,7 +648,7 @@
"refId": "A" "refId": "A"
} }
], ],
"title": "Disk usage by user", "title": "disk usage by user",
"type": "piechart" "type": "piechart"
}, },
{ {
@ -681,7 +681,7 @@
"x": 0, "x": 0,
"y": 7 "y": 7
}, },
"hideTimeOverride": false, "hideTimeOverride": true,
"id": 28, "id": 28,
"options": { "options": {
"colorMode": "background", "colorMode": "background",
@ -705,13 +705,13 @@
"uid": "${DS_PROMETHEUS}" "uid": "${DS_PROMETHEUS}"
}, },
"editorMode": "code", "editorMode": "code",
"expr": "increase(immich_server_stats_usage_growth[4w])", "expr": "increase(immich_server_stats_usage_growth[30h])",
"legendFormat": "__auto", "legendFormat": "__auto",
"range": true, "range": true,
"refId": "A" "refId": "A"
} }
], ],
"timeFrom": "1M", "timeFrom": "now/M",
"title": "Monthly data growth", "title": "Monthly data growth",
"type": "stat" "type": "stat"
}, },
@ -745,7 +745,7 @@
"x": 6, "x": 6,
"y": 7 "y": 7
}, },
"hideTimeOverride": false, "hideTimeOverride": true,
"id": 30, "id": 30,
"options": { "options": {
"colorMode": "background", "colorMode": "background",
@ -769,14 +769,14 @@
"uid": "${DS_PROMETHEUS}" "uid": "${DS_PROMETHEUS}"
}, },
"editorMode": "code", "editorMode": "code",
"expr": "increase(immich_server_stats_usage_growth[1y])", "expr": "increase(immich_server_stats_useage_growth[365d])",
"legendFormat": "__auto", "legendFormat": "__auto",
"range": true, "range": true,
"refId": "A" "refId": "A"
} }
], ],
"timeFrom": "1y", "timeFrom": "now/y",
"title": "Yearly data growth", "title": "Yealy data growth",
"type": "stat" "type": "stat"
}, },
{ {
@ -837,7 +837,7 @@
} }
], ],
"timeFrom": "now/d", "timeFrom": "now/d",
"title": "Daily photos growth", "title": "daily photos growth",
"type": "stat" "type": "stat"
}, },
{ {
@ -897,8 +897,8 @@
"refId": "A" "refId": "A"
} }
], ],
"timeFrom": "1w", "timeFrom": "now/w",
"title": "Weekly photos growth", "title": "weekly photos growth",
"type": "stat" "type": "stat"
}, },
{ {
@ -1029,7 +1029,7 @@
"refId": "A" "refId": "A"
} }
], ],
"timeFrom": "1M", "timeFrom": "now/M",
"title": "Monthly photos growth", "title": "Monthly photos growth",
"type": "stat" "type": "stat"
}, },
@ -1086,14 +1086,14 @@
"uid": "${DS_PROMETHEUS}" "uid": "${DS_PROMETHEUS}"
}, },
"editorMode": "code", "editorMode": "code",
"expr": "increase(immich_server_stats_photos_growth[1y])", "expr": "increase(immich_server_stats_photos_growth[52w])",
"legendFormat": "__auto", "legendFormat": "__auto",
"range": true, "range": true,
"refId": "A" "refId": "A"
} }
], ],
"timeFrom": "1y", "timeFrom": "now/y",
"title": "Yearly photos growth", "title": "yearly photos growth",
"type": "stat" "type": "stat"
}, },
{ {
@ -1160,7 +1160,7 @@
"x": 0, "x": 0,
"y": 19 "y": 19
}, },
"hideTimeOverride": false, "hideTimeOverride": true,
"id": 22, "id": 22,
"options": { "options": {
"legend": { "legend": {
@ -1187,103 +1187,8 @@
"refId": "A" "refId": "A"
} }
], ],
"timeFrom": "1M", "timeFrom": "now/M",
"title": "Photos Growth", "title": "Monthly Photos Growth",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"description": "amount of photos over time",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "right",
"axisSoftMin": 9000,
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 30,
"gradientMode": "opacity",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineStyle": {
"fill": "solid"
},
"lineWidth": 1,
"pointSize": 1,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": true,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 7,
"w": 24,
"x": 0,
"y": 26
},
"hideTimeOverride": false,
"id": 47,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"expr": "immich_server_stats_photos_by_users",
"legendFormat": "{{firstName}}",
"range": true,
"refId": "A"
}
],
"timeFrom": "1y",
"title": "Photos Growth",
"type": "timeseries" "type": "timeseries"
}, },
{ {
@ -1301,7 +1206,8 @@
"mode": "absolute", "mode": "absolute",
"steps": [ "steps": [
{ {
"color": "green" "color": "green",
"value": null
} }
] ]
} }
@ -1312,7 +1218,7 @@
"h": 4, "h": 4,
"w": 6, "w": 6,
"x": 0, "x": 0,
"y": 33 "y": 26
}, },
"hideTimeOverride": true, "hideTimeOverride": true,
"id": 42, "id": 42,
@ -1345,7 +1251,7 @@
} }
], ],
"timeFrom": "now/d", "timeFrom": "now/d",
"title": "Daily video growth", "title": "daily video growth",
"type": "stat" "type": "stat"
}, },
{ {
@ -1363,7 +1269,8 @@
"mode": "absolute", "mode": "absolute",
"steps": [ "steps": [
{ {
"color": "green" "color": "green",
"value": null
} }
] ]
} }
@ -1374,7 +1281,7 @@
"h": 4, "h": 4,
"w": 6, "w": 6,
"x": 6, "x": 6,
"y": 33 "y": 26
}, },
"hideTimeOverride": true, "hideTimeOverride": true,
"id": 40, "id": 40,
@ -1406,8 +1313,8 @@
"refId": "A" "refId": "A"
} }
], ],
"timeFrom": "1w", "timeFrom": "now/w",
"title": "Weekly videos growth", "title": "weekly videos growth",
"type": "stat" "type": "stat"
}, },
{ {
@ -1435,7 +1342,7 @@
"h": 8, "h": 8,
"w": 12, "w": 12,
"x": 12, "x": 12,
"y": 33 "y": 26
}, },
"id": 6, "id": 6,
"options": { "options": {
@ -1474,7 +1381,7 @@
"refId": "A" "refId": "A"
} }
], ],
"title": "Videos", "title": "videos",
"type": "piechart" "type": "piechart"
}, },
{ {
@ -1503,7 +1410,7 @@
"h": 4, "h": 4,
"w": 6, "w": 6,
"x": 0, "x": 0,
"y": 37 "y": 30
}, },
"hideTimeOverride": true, "hideTimeOverride": true,
"id": 44, "id": 44,
@ -1521,7 +1428,7 @@
}, },
"textMode": "auto" "textMode": "auto"
}, },
"pluginVersion": "10.0.2", "pluginVersion": "9.4.3",
"targets": [ "targets": [
{ {
"datasource": { "datasource": {
@ -1535,7 +1442,7 @@
"refId": "A" "refId": "A"
} }
], ],
"timeFrom": "1M", "timeFrom": "now/M",
"title": "Monthly videos growth", "title": "Monthly videos growth",
"type": "stat" "type": "stat"
}, },
@ -1565,7 +1472,7 @@
"h": 4, "h": 4,
"w": 6, "w": 6,
"x": 6, "x": 6,
"y": 37 "y": 30
}, },
"hideTimeOverride": true, "hideTimeOverride": true,
"id": 46, "id": 46,
@ -1583,7 +1490,7 @@
}, },
"textMode": "auto" "textMode": "auto"
}, },
"pluginVersion": "10.0.2", "pluginVersion": "9.4.3",
"targets": [ "targets": [
{ {
"datasource": { "datasource": {
@ -1591,14 +1498,14 @@
"uid": "${DS_PROMETHEUS}" "uid": "${DS_PROMETHEUS}"
}, },
"editorMode": "code", "editorMode": "code",
"expr": "increase(immich_server_stats_videos_growth[1y])\r\n", "expr": "increase(immich_server_stats_videos_growth[52w])\r\n",
"legendFormat": "__auto", "legendFormat": "__auto",
"range": true, "range": true,
"refId": "A" "refId": "A"
} }
], ],
"timeFrom": "1y", "timeFrom": "now/y",
"title": "Yearly video growth", "title": "Panel Title",
"type": "stat" "type": "stat"
}, },
{ {
@ -1661,7 +1568,7 @@
"h": 8, "h": 8,
"w": 24, "w": 24,
"x": 0, "x": 0,
"y": 41 "y": 34
}, },
"id": 20, "id": 20,
"options": { "options": {
@ -1689,99 +1596,7 @@
"refId": "A" "refId": "A"
} }
], ],
"timeFrom": "1M", "timeFrom": "now/M",
"title": "Videos growth",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"description": "amount of videos over time",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "right",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 30,
"gradientMode": "opacity",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineStyle": {
"fill": "solid"
},
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": true,
"stacking": {
"group": "A",
"mode": "normal"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green"
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 24,
"x": 0,
"y": 49
},
"id": 48,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"expr": "immich_server_stats_videos_by_users",
"legendFormat": "{{firstName}}",
"range": true,
"refId": "A"
}
],
"timeFrom": "1y",
"title": "Videos growth", "title": "Videos growth",
"type": "timeseries" "type": "timeseries"
} }
@ -1802,6 +1617,6 @@
"timezone": "", "timezone": "",
"title": "immich", "title": "immich",
"uid": "ZWWp3aa4k", "uid": "ZWWp3aa4k",
"version": 9, "version": 1,
"weekStart": "" "weekStart": ""
} }

View file

@ -39,7 +39,6 @@ class ImmichMetricsCollector:
yield prom_metric yield prom_metric
def get_immich_metrics(self): def get_immich_metrics(self):
metrics = [] metrics = []
metrics.extend(self.get_immich_server_version_number()) metrics.extend(self.get_immich_server_version_number())
metrics.extend(self.get_immich_server_info()) metrics.extend(self.get_immich_server_info())
@ -48,7 +47,6 @@ class ImmichMetricsCollector:
return metrics return metrics
def get_immich_users_stat_growth(self): def get_immich_users_stat_growth(self):
try: try:
@ -212,27 +210,24 @@ class ImmichMetricsCollector:
] ]
def get_immich_server_version_number(self): def get_immich_server_version_number(self):
# Requesting immich_server_number serves two purposes. As the name says it returns the version number
# 1. get version the full server version number
# 2. check if immich api key is correct
# throwing connectionRefused exception usually means that immich isn't running
server_version_endpoint = "/api/server-info/version" server_version_endpoint = "/api/server-info/version"
response_server_version = "" response_server_version = ""
while True: for i in range(0, 360):
try: while True:
try:
response_server_version = requests.request( response_server_version = requests.request(
"GET", "GET",
self.combine_url(server_version_endpoint), self.combine_url(server_version_endpoint),
headers={'Accept': 'application/json', headers={'Accept': 'application/json',
"x-api-key": self.config["token"]} "x-api-key": self.config["token"]}
) )
except requests.exceptions.RequestException as e: except requests.exceptions.RequestException as e:
logger.error(f"Couldn't get server version") logger.error(f"Couldn't get server version: {e}")
continue continue
break break
server_version_number = (str(response_server_version.json()["major"]) + "." + server_version_number = (str(response_server_version.json()["major"]) + "." +
str(response_server_version.json()["minor"]) + "." + str(response_server_version.json()["minor"]) + "." +
@ -258,7 +253,6 @@ class ImmichMetricsCollector:
return combined_url return combined_url
# test
class SignalHandler(): class SignalHandler():
def __init__(self): def __init__(self):
self.shutdownCount = 0 self.shutdownCount = 0
@ -290,58 +284,6 @@ def get_config_value(key, default=""):
return os.environ.get(key, default) return os.environ.get(key, default)
def check_server_up(immichHost, immichPort):
#
counter = 0
while True:
counter = counter + 1
try:
requests.request(
"GET",
"http://" + immichHost + ":" + immichPort + "/api/server-info/ping",
headers={'Accept': 'application/json'}
)
except requests.exceptions.RequestException as e:
logger.error(f"CONNECTION ERROR. Cannot reach immich at " + immichHost + ":" + immichPort + "."
f"Is immich up and running?")
if 0 <= counter <= 60:
time.sleep(1)
elif 11 <= counter <= 300:
time.sleep(15)
elif counter > 300:
time.sleep(60)
continue
break
logger.info(f"Found immich up and running at " + immichHost + ":" + immichPort + ".")
logger.info(f"Attempting to connect")
time.sleep(1)
logger.info("Exporter v1.0.6")
def check_immich_api_key(immichHost, immichPort, immichApiKey):
while True:
try:
requests.request(
"GET",
"http://"+immichHost+":"+immichPort+"/api/server-info/",
headers={'Accept': 'application/json',
"x-api-key": immichApiKey}
)
except requests.exceptions.RequestException as e:
logger.error(f"CONNECTION ERROR. Possible API key error")
logger.error({e})
time.sleep(3)
continue
logger.info(f"Connected to immich successfully")
break
def main(): def main():
# Init logger so it can be used # Init logger so it can be used
logHandler = logging.StreamHandler() logHandler = logging.StreamHandler()
@ -379,21 +321,15 @@ def main():
# Register our custom collector # Register our custom collector
logger.info("Exporter is starting up") logger.info("Exporter is starting up")
check_server_up(config["immich_host"], config["immich_port"])
check_immich_api_key(config["immich_host"], config["immich_port"], config["token"])
REGISTRY.register(ImmichMetricsCollector(config)) REGISTRY.register(ImmichMetricsCollector(config))
# Start server # Start server
start_http_server(config["exporter_port"]) start_http_server(config["exporter_port"])
logger.info( logger.info(
f"Exporter listening on port {config['exporter_port']}" f"Exporter listening on port {config['exporter_port']}"
) )
while not signal_handler.is_shutting_down(): while not signal_handler.is_shutting_down():
time.sleep(1) time.sleep(1)
logger.info("Exporter has shutdown") logger.info("Exporter has shutdown")

View file

@ -6,7 +6,7 @@ with open("README.md", "r") as fh:
setup( setup(
name='prometheus-immich-exporter', name='prometheus-immich-exporter',
packages=['immich_exporter'], packages=['immich_exporter'],
version='1.0.6', version='1.0.1',
long_description=long_description, long_description=long_description,
long_description_content_type="text/markdown", long_description_content_type="text/markdown",
description='Prometheus exporter for immich', description='Prometheus exporter for immich',

View file

@ -18,11 +18,11 @@
<PostArgs/> <PostArgs/>
<CPUset/> <CPUset/>
<DateInstalled>1678876858</DateInstalled> <DateInstalled>1678876858</DateInstalled>
<DonateText>If you like my work, consider supporting me.</DonateText> <DonateText>If I made your day a little bit brighter, consider donating.</DonateText>
<DonateLink>https://www.paypal.com/donate/?hosted_button_id=DPDKED3T3BFV8</DonateLink> <DonateLink>https://www.paypal.com/donate/?hosted_button_id=DPDKED3T3BFV8</DonateLink>
<Requires/> <Requires/>
<Config Name="Immich_exporter_port" Target="8000" Default="8000" Mode="tcp" Description="" Type="Port" Display="always" Required="false" Mask="false">8000</Config> <Config Name="Host Port 1" Target="8000" Default="8028" Mode="tcp" Description="" Type="Port" Display="always" Required="false" Mask="false">8028</Config>
<Config Name="immich api token" Target="IMMICH_API_TOKEN" Default="" Mode="" Description="You need to log into to your immich admin account&#13;&#10;and create an api token in your settings" Type="Variable" Display="always" Required="false" Mask="false"/> <Config Name="immich api token" Target="IMMICH_API_TOKEN" Default="" Mode="" Description="You need to log into to your immich admin account&#13;&#10;and create an api token in your settings" Type="Variable" Display="always" Required="false" Mask="false"/>
<Config Name="immich_host" Target="IMMICH_HOST" Default="" Mode="" Description="Address to Immich_proxy, example: 192.168.178.2" Type="Variable" Display="always" Required="false" Mask="false"/> <Config Name="immich_host" Target="IMMICH_HOST" Default="" Mode="" Description="example: 192.168.178.2" Type="Variable" Display="always" Required="false" Mask="false"/>
<Config Name="immich port" Target="IMMICH_PORT" Default="8080" Mode="" Description="Port for Immich_proxy" Type="Variable" Display="always" Required="false" Mask="false"/> <Config Name="immich port" Target="IMMICH_PORT" Default="" Mode="" Description="" Type="Variable" Display="always" Required="false" Mask="false"/>
</Container> </Container>