Merge branch 'claude/2' into main

- Data-driven Eleventy marketing site (site/)
- HOST_NAME honoured for subdomains + @ apex hosting
- Dynamic per-port subdomains with router-block toggle (all apps converted)
- Split-horizon local DNS (AdGuard wildcard + Pi-hole hosts)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
This commit is contained in:
librelad 2026-05-22 10:59:48 +01:00
commit 36e0d31385
111 changed files with 4812 additions and 89 deletions

View File

@ -65,7 +65,7 @@ CFG_ADGUARD_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_ADGUARD_PORT_1="adguard-service|webui|random:3000|public|tcp|true|true|true|Admin Interface|"
CFG_ADGUARD_PORT_1="adguard-service|webui|random:3000|public|tcp|true|true|true|Admin Interface||adguard"
CFG_ADGUARD_PORT_2="adguard-service|dns-tcp|random:53|public|tcp|false|false|false|DNS Server (TCP)|"
CFG_ADGUARD_PORT_3="adguard-service|dns-udp|random:53|public|udp|false|false|false|DNS Server (UDP)|"
CFG_ADGUARD_PORT_4="adguard-service|dns-alt|random:8053|disabled|tcp|false|false|false|Alternative DNS|"

View File

@ -20,13 +20,15 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.adguard-service-webui.entrypoints: web,websecure
traefik.http.routers.adguard-service-webui.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.adguard-service-webui.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.adguard-service-webui.service: adguard-service-webui
traefik.http.routers.adguard-service-webui.tls: true
traefik.http.routers.adguard-service-webui.tls.certresolver: production
traefik.http.services.adguard-service-webui.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.adguard-service-webui.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
healthcheck:
disable: HEALTHCHECK_DATA #LIBREPORTAL|HEALTHCHECK_TAG|HEALTHCHECK_DATA
volumes:

View File

@ -71,4 +71,4 @@ CFG_AUTHELIA_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_AUTHELIA_PORT_1="authelia-service|webui|random:9091|public|tcp|false|true|true|Web Interface|"
CFG_AUTHELIA_PORT_1="authelia-service|webui|random:9091|public|tcp|false|true|true|Web Interface||authelia"

View File

@ -24,12 +24,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.authelia-service.entrypoints: web,websecure
traefik.http.routers.authelia-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.authelia-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.authelia-service.tls: true
traefik.http.routers.authelia-service.tls.certresolver: production
traefik.http.services.authelia-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.authelia-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.authelia-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
traefik.docker.network: DOCKER_NETWORK_DATA #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
healthcheck:
disable: HEALTHCHECK_DATA #LIBREPORTAL|HEALTHCHECK_TAG|HEALTHCHECK_DATA

View File

@ -69,7 +69,7 @@ CFG_BOOKSTACK_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_BOOKSTACK_PORT_1="bookstack-service|webui|random:80|public|tcp|false|true|true|Web Interface|"
CFG_BOOKSTACK_PORT_1="bookstack-service|webui|random:80|public|tcp|false|true|true|Web Interface||bookstack"
# AUTH_PROFILE = capability tier for the WebUI auth tools (single_password | user_password | multi_user)
CFG_BOOKSTACK_AUTH_PROFILE=multi_user

View File

@ -33,12 +33,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.bookstack-service.entrypoints: web,websecure
traefik.http.routers.bookstack-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.bookstack-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.bookstack-service.tls: true
traefik.http.routers.bookstack-service.tls.certresolver: production
traefik.http.services.bookstack-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.bookstack-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.bookstack-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
traefik.docker.network: DOCKER_NETWORK_DATA #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
# GLUETUN_OFF_BEGIN
networks:

View File

@ -59,7 +59,7 @@ CFG_DASHY_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_DASHY_PORT_1="dashy-service|webui|random:8080|private|tcp|false|false|true|Dashboard|"
CFG_DASHY_PORT_1="dashy-service|webui|random:8080|private|tcp|false|false|true|Dashboard||dashy"
# Comma-separated list of installed app slugs to surface as shortcuts on
# the dashy dashboard. Managed via the Tools tab → "Manage Shortcuts".
# Empty = no app shortcuts (only the static page header survives).

View File

@ -28,12 +28,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.dashy-service.entrypoints: web,websecure
traefik.http.routers.dashy-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.dashy-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.dashy-service.tls: true
traefik.http.routers.dashy-service.tls.certresolver: production
traefik.http.services.dashy-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.dashy-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.dashy-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
traefik.docker.network: DOCKER_NETWORK_DATA #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
# GLUETUN_OFF_BEGIN
networks:

View File

@ -23,12 +23,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.focalboard-service.entrypoints: web,websecure
traefik.http.routers.focalboard-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.focalboard-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.focalboard-service.tls: true
traefik.http.routers.focalboard-service.tls.certresolver: production
traefik.http.services.focalboard-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.focalboard-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.focalboard-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
traefik.docker.network: DOCKER_NETWORK_DATA #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
# GLUETUN_OFF_BEGIN
networks:

View File

@ -59,7 +59,7 @@ CFG_FOCALBOARD_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_FOCALBOARD_PORT_1="focalboard-service|webui|random:8000|public|tcp|false|true|true|Web Interface|"
CFG_FOCALBOARD_PORT_1="focalboard-service|webui|random:8000|public|tcp|false|true|true|Web Interface||board"
# AUTH_PROFILE = capability tier for the WebUI auth tools (single_password | user_password | multi_user)
CFG_FOCALBOARD_AUTH_PROFILE=multi_user

View File

@ -65,12 +65,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.gitea-service.entrypoints: web,websecure
traefik.http.routers.gitea-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.gitea-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.gitea.tls: true
traefik.http.routers.gitea.tls.certresolver: production
traefik.http.services.gitea.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.gitea.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.gitea.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
traefik.docker.network: DOCKER_NETWORK_DATA #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
gitea-cache: #LIBREPORTAL|SERVICE_TAG_2|gitea-cache

View File

@ -63,7 +63,7 @@ CFG_GITEA_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_GITEA_PORT_1="gitea-service|webui|random:3000|public|tcp|false|true|true|Web Interface|"
CFG_GITEA_PORT_1="gitea-service|webui|random:3000|public|tcp|false|true|true|Web Interface||gitea"
CFG_GITEA_PORT_2="gitea-service|ssh|random:22|private|tcp|false|false|false|Git SSH Access|"
# AUTH_PROFILE = capability tier for the WebUI auth tools (single_password | user_password | multi_user)

View File

@ -24,12 +24,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.grafana-service.entrypoints: web,websecure
traefik.http.routers.grafana-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.grafana-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.grafana-service.tls: true
traefik.http.routers.grafana-service.tls.certresolver: production
traefik.http.services.grafana-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.grafana-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.grafana-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
traefik.docker.network: DOCKER_NETWORK_DATA #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
healthcheck:
disable: HEALTHCHECK_DATA #LIBREPORTAL|HEALTHCHECK_TAG|HEALTHCHECK_DATA

View File

@ -64,4 +64,4 @@ CFG_GRAFANA_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_GRAFANA_PORT_1="grafana-service|webui|random:3000|public|tcp|false|true|true|Web Interface|"
CFG_GRAFANA_PORT_1="grafana-service|webui|random:3000|public|tcp|false|true|true|Web Interface||grafana"

View File

@ -56,9 +56,11 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
traefik.http.routers.headscale-webui-service.rule: Host(`admin.DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
# TRAEFIK_PORT_2_BEGIN
traefik.http.routers.headscale-webui-service.rule: Host(`DOMAINSUBNAME_DATA_2`) #LIBREPORTAL|DOMAINSUBNAME_TAG_2|DOMAINSUBNAME_DATA_2
traefik.http.services.headscale-webui-service.loadbalancer.server.port: PORT_INTERNAL_DATA_2 #LIBREPORTAL|PORT_INTERNAL_TAG_2|PORT_INTERNAL_DATA_2
traefik.http.routers.headscale-webui-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.headscale-webui-service.middlewares: MIDDLEWARE_DATA_2 #LIBREPORTAL|MIDDLEWARE_TAG_2|MIDDLEWARE_DATA_2
# TRAEFIK_PORT_2_END
traefik.docker.network: DOCKER_NETWORK_DATA #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
ports:
- "PORTS_DATA_2" #LIBREPORTAL|PORTS_TAG_2|PORTS_DATA_2

View File

@ -60,4 +60,4 @@ CFG_HEADSCALE_NETWORK=default
# - description: human-readable description of the service
#
CFG_HEADSCALE_PORT_1="headscale-service|api|random:8080|private|tcp|false|false|false|Headscale API Server|"
CFG_HEADSCALE_PORT_2="headscale-webui-service|webui|random:5000|private|tcp|false|true|true|Web UI|"
CFG_HEADSCALE_PORT_2="headscale-webui-service|webui|random:5000|private|tcp|false|true|true|Web UI||admin.headscale"

View File

@ -43,12 +43,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.invidious-service.entrypoints: web,websecure
traefik.http.routers.invidious-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.invidious-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.invidious-service.tls: true
traefik.http.routers.invidious-service.tls.certresolver: production
traefik.http.services.invidious-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.invidious-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.invidious-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
traefik.docker.network: DOCKER_NETWORK_DATA #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
# GLUETUN_OFF_BEGIN
networks:

View File

@ -62,7 +62,7 @@ CFG_INVIDIOUS_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_INVIDIOUS_PORT_1="invidious-service|webui|random:3000|public|tcp|false|true|true|Web Interface|"
CFG_INVIDIOUS_PORT_1="invidious-service|webui|random:3000|public|tcp|false|true|true|Web Interface||invidious"
# AUTH_PROFILE = capability tier for the WebUI auth tools (single_password | user_password | multi_user)
CFG_INVIDIOUS_AUTH_PROFILE=multi_user

View File

@ -17,12 +17,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.ipinfo-service.entrypoints: web,websecure
traefik.http.routers.ipinfo-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.ipinfo-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.ipinfo-service.tls: true
traefik.http.routers.ipinfo-service.tls.certresolver: production
traefik.http.services.ipinfo-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.ipinfo-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.ipinfo-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
traefik.docker.network: DOCKER_NETWORK_DATA #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
healthcheck:
disable: HEALTHCHECK_DATA #LIBREPORTAL|HEALTHCHECK_TAG|HEALTHCHECK_DATA

View File

@ -59,4 +59,4 @@ CFG_IPINFO_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_IPINFO_PORT_1="ipinfo-service|webui|random:8080|public|tcp|false|true|true|Web Interface|"
CFG_IPINFO_PORT_1="ipinfo-service|webui|random:8080|public|tcp|false|true|true|Web Interface||ipinfo"

View File

@ -21,12 +21,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.jellyfin-service.entrypoints: web,websecure
traefik.http.routers.jellyfin-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.jellyfin-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.jellyfin-service.tls: true
traefik.http.routers.jellyfin-service.tls.certresolver: production
traefik.http.services.jellyfin-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.jellyfin-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.jellyfin-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
traefik.docker.network: DOCKER_NETWORK_DATA #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
healthcheck:
disable: HEALTHCHECK_DATA #LIBREPORTAL|HEALTHCHECK_TAG|HEALTHCHECK_DATA

View File

@ -59,4 +59,4 @@ CFG_JELLYFIN_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_JELLYFIN_PORT_1="jellyfin-service|webui|random:8096|public|tcp|false|true|true|Media Server|"
CFG_JELLYFIN_PORT_1="jellyfin-service|webui|random:8096|public|tcp|false|true|true|Media Server||jellyfin"

View File

@ -23,12 +23,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.jitsimeet-service.entrypoints: web,websecure
traefik.http.routers.jitsimeet-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.jitsimeet-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.jitsimeet-service.tls: true
traefik.http.routers.jitsimeet-service.tls.certresolver: production
traefik.http.services.jitsimeet-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.jitsimeet-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.jitsimeet-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
traefik.docker.network: DOCKER_NETWORK_DATA #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
networks:
DOCKER_NETWORK_DATA: #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA

View File

@ -59,6 +59,6 @@ CFG_JITSIMEET_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_JITSIMEET_PORT_1="jitsimeet-service|webui|random:80|public|tcp|false|true|true|Web Interface|"
CFG_JITSIMEET_PORT_1="jitsimeet-service|webui|random:80|public|tcp|false|true|true|Web Interface||meet"
CFG_JITSIMEET_PORT_2="jitsimeet-jvb|video-bridge|random:10000|public|udp|false|false|false|Jitsi Video Bridge (UDP)|"
CFG_JITSIMEET_PORT_3="jitsimeet-jvb|video-tcp|random:30300|public|tcp|false|false|false|Jitsi Video Bridge (TCP)|"

View File

@ -36,12 +36,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.libreportal-service.entrypoints: web,websecure
traefik.http.routers.libreportal-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.libreportal-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.libreportal-service.tls: true
traefik.http.routers.libreportal-service.tls.certresolver: production
traefik.http.services.libreportal-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.libreportal-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.libreportal-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
traefik.docker.network: DOCKER_NETWORK_DATA #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
healthcheck:
disable: HEALTHCHECK_DATA #LIBREPORTAL|HEALTHCHECK_TAG|HEALTHCHECK_DATA

View File

@ -59,4 +59,4 @@ CFG_LIBREPORTAL_HOST_NAME=libreportal
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_LIBREPORTAL_PORT_1="libreportal-service|webui|random:1111|public|tcp|false|false|true|Web Interface|"
CFG_LIBREPORTAL_PORT_1="libreportal-service|webui|random:1111|public|tcp|false|false|true|Web Interface||libreportal"

View File

@ -19,12 +19,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.linkding-service.entrypoints: web,websecure
traefik.http.routers.linkding-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.linkding-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.linkding-service.tls: true
traefik.http.routers.linkding-service.tls.certresolver: production
traefik.http.services.linkding-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.linkding-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.linkding-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
traefik.docker.network: DOCKER_NETWORK_DATA #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
healthcheck:
disable: HEALTHCHECK_DATA #LIBREPORTAL|HEALTHCHECK_TAG|HEALTHCHECK_DATA

View File

@ -59,4 +59,4 @@ CFG_LINKDING_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_LINKDING_PORT_1="linkding-service|webui|random:9090|public|tcp|false|true|true|Web Interface|"
CFG_LINKDING_PORT_1="linkding-service|webui|random:9090|public|tcp|false|true|true|Web Interface||bookmark"

View File

@ -37,12 +37,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.mastodon-service.entrypoints: web,websecure
traefik.http.routers.mastodon-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.mastodon-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.mastodon-service.tls: true
traefik.http.routers.mastodon-service.tls.certresolver: production
traefik.http.services.mastodon-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.mastodon-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.mastodon-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
traefik.docker.network: DOCKER_NETWORK_DATA #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
command: bash -c "RAILS_ENV=production bundle exec rails db:migrate && RAILS_ENV=production bundle exec rails s -b 0.0.0.0"
healthcheck:

View File

@ -59,5 +59,5 @@ CFG_MASTODON_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_MASTODON_PORT_1="mastodon-service|webui|random:3010|public|tcp|false|false|true|Web Interface|"
CFG_MASTODON_PORT_1="mastodon-service|webui|random:3010|public|tcp|false|false|true|Web Interface||social"
CFG_MASTODON_PORT_2="mastodon-service|streaming|random:4010|public|tcp|false|false|false|Mastodon Streaming API|"

View File

@ -31,12 +31,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.moneyapp-service.entrypoints: web,websecure
traefik.http.routers.moneyapp-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.moneyapp-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.moneyapp-service.tls: true
traefik.http.routers.moneyapp-service.tls.certresolver: production
traefik.http.services.moneyapp-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.moneyapp-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.moneyapp-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
traefik.docker.network: DOCKER_NETWORK_DATA #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
# GLUETUN_OFF_BEGIN
networks:

View File

@ -55,4 +55,4 @@ CFG_MONEYAPP_NETWORK=default
# Schema (10 cols): service|name|external:internal|access|protocol|login|traefik|button_enabled|button_text|url_path
# button_text + url_path may carry comma-separated parallel arrays for multi-button entries.
#
CFG_MONEYAPP_PORT_1="moneyapp-service|webui|random:3000|public|tcp|false|true|true|MoneyApp|/"
CFG_MONEYAPP_PORT_1="moneyapp-service|webui|random:3000|public|tcp|false|true|true|MoneyApp|/|moneyapp"

View File

@ -32,12 +32,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.nextcloud-service.entrypoints: web,websecure
traefik.http.routers.nextcloud-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.nextcloud-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.nextcloud-service.tls: true
traefik.http.routers.nextcloud-service.tls.certresolver: production
traefik.http.services.nextcloud-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.nextcloud-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.nextcloud-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
traefik.docker.network: DOCKER_NETWORK_DATA #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
# GLUETUN_OFF_BEGIN
networks:

View File

@ -71,5 +71,5 @@ CFG_NEXTCLOUD_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_NEXTCLOUD_PORT_1="nextcloud-service|webui|random:80|public|tcp|false|true|true|Web Interface|"
CFG_NEXTCLOUD_PORT_1="nextcloud-service|webui|random:80|public|tcp|false|true|true|Web Interface||nextcloud"
CFG_NEXTCLOUD_PORT_2="nextcloud-exporter|metrics|9205:9205|disabled|tcp|false|false|false|Metrics Exporter (sidecar, docker-network only)|"

View File

@ -19,12 +19,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.ollama-webui.entrypoints: web,websecure
traefik.http.routers.ollama-webui.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.ollama-webui.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.ollama-webui.tls: true
traefik.http.routers.ollama-webui.tls.certresolver: production
traefik.http.services.ollama-webui.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.ollama-webui.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.ollama-webui.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
healthcheck:
disable: HEALTHCHECK_DATA #LIBREPORTAL|HEALTHCHECK_TAG|HEALTHCHECK_DATA
networks:

View File

@ -61,6 +61,6 @@ CFG_OLLAMA_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_OLLAMA_PORT_1="ollama-webui|webui|random:8080|public|tcp|false|true|true|Web Interface|"
CFG_OLLAMA_PORT_1="ollama-webui|webui|random:8080|public|tcp|false|true|true|Web Interface||ollama"
CFG_OLLAMA_PORT_2="ollama-service|api|random:11434|private|tcp|false|false|false|Ollama API|"
CFG_OLLAMA_PORT_3="ollama-exporter|metrics|9778:9778|disabled|tcp|false|false|false|Metrics Exporter (sidecar, docker-network only)|"

View File

@ -18,15 +18,17 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.onlyoffice-service.entrypoints: web,websecure
traefik.http.routers.onlyoffice-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.onlyoffice-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.onlyoffice-service.tls: true
traefik.http.routers.onlyoffice-service.tls.certresolver: production
traefik.http.services.onlyoffice-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.onlyoffice-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.onlyoffice-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# Headers for onlyoffice, https://github.com/ONLYOFFICE/onlyoffice-nextcloud/issues/151
traefik.http.middlewares.onlyoffice-headers.headers.customrequestheaders.X-Forwarded-Proto: https
traefik.http.middlewares.onlyoffice-headers.headers.accesscontrolalloworiginlist: "*"
# TRAEFIK_PORT_1_END
healthcheck:
disable: HEALTHCHECK_DATA #LIBREPORTAL|HEALTHCHECK_TAG|HEALTHCHECK_DATA
volumes:

View File

@ -59,4 +59,4 @@ CFG_ONLYOFFICE_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_ONLYOFFICE_PORT_1="onlyoffice-service|webui|random:80|public|tcp|false|true|true|Web Interface|"
CFG_ONLYOFFICE_PORT_1="onlyoffice-service|webui|random:80|public|tcp|false|true|true|Web Interface||onlyoffice"

View File

@ -33,12 +33,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.owncloud-service.entrypoints: web,websecure
traefik.http.routers.owncloud-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.owncloud-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.owncloud-service.tls: true
traefik.http.routers.owncloud-service.tls.certresolver: production
traefik.http.services.owncloud-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.owncloud-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.owncloud-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
traefik.docker.network: DOCKER_NETWORK_DATA #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
healthcheck:
test: ["CMD", "/usr/bin/healthcheck"]

View File

@ -69,4 +69,4 @@ CFG_OWNCLOUD_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_OWNCLOUD_PORT_1="owncloud-service|webui|random:8080|public|tcp|false|true|true|Web Interface|"
CFG_OWNCLOUD_PORT_1="owncloud-service|webui|random:8080|public|tcp|false|true|true|Web Interface||cloud"

View File

@ -20,12 +20,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.pihole-service.entrypoints: web,websecure
traefik.http.routers.pihole-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.pihole-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.pihole-service.tls: true
traefik.http.routers.pihole-service.tls.certresolver: production
traefik.http.services.pihole-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.pihole-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.pihole-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
environment:
- FTLCONF_LOCAL_IPV4=PUBLIC_IP_DATA #LIBREPORTAL|PUBLIC_IP_TAG|PUBLIC_IP_DATA
- TZ=TIMEZONE_DATA #LIBREPORTAL|TIMEZONE_TAG|TIMEZONE_DATA

View File

@ -70,7 +70,7 @@ CFG_PIHOLE_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_PIHOLE_PORT_1="pihole-service|webui|random:80|private|tcp|false|false|true|Admin Interface|/admin/"
CFG_PIHOLE_PORT_1="pihole-service|webui|random:80|private|tcp|false|false|true|Admin Interface|/admin/|pihole"
CFG_PIHOLE_PORT_2="pihole-service|dns-tcp|53:53|private|tcp|false|false|false|DNS Server (TCP)|"
CFG_PIHOLE_PORT_3="pihole-service|dns-udp|53:53|private|udp|false|false|false|DNS Server (UDP)|"
CFG_PIHOLE_PORT_4="pihole-service|https|random:443|disabled|tcp|false|false|false|HTTPS Interface|"

View File

@ -21,12 +21,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.prometheus-service.entrypoints: web,websecure
traefik.http.routers.prometheus-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.prometheus-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.prometheus-service.tls: true
traefik.http.routers.prometheus-service.tls.certresolver: production
traefik.http.services.prometheus-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.prometheus-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.prometheus-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
healthcheck:
disable: HEALTHCHECK_DATA #LIBREPORTAL|HEALTHCHECK_TAG|HEALTHCHECK_DATA
volumes:

View File

@ -59,4 +59,4 @@ CFG_PROMETHEUS_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_PROMETHEUS_PORT_1="prometheus-service|webui|random:9090|public|tcp|false|true|true|Web Interface|"
CFG_PROMETHEUS_PORT_1="prometheus-service|webui|random:9090|public|tcp|false|true|true|Web Interface||prometheus"

View File

@ -16,12 +16,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.searxng-service.entrypoints: web,websecure
traefik.http.routers.searxng-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.searxng-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.searxng-service.tls: true
traefik.http.routers.searxng-service.tls.certresolver: production
traefik.http.services.searxng-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.searxng-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.searxng-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
cap_drop:
- ALL
cap_add:

View File

@ -66,4 +66,4 @@ CFG_SEARXNG_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_SEARXNG_PORT_1="searxng-service|webui|8083:8080|public|tcp|false|true|true|Search Interface|"
CFG_SEARXNG_PORT_1="searxng-service|webui|8083:8080|public|tcp|false|true|true|Search Interface||search"

View File

@ -24,12 +24,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.speedtest-service.entrypoints: web,websecure
traefik.http.routers.speedtest-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.speedtest-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.speedtest-service.tls: true
traefik.http.routers.speedtest-service.tls.certresolver: production
traefik.http.services.speedtest-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.speedtest-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.speedtest-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
healthcheck:
disable: HEALTHCHECK_DATA #LIBREPORTAL|HEALTHCHECK_TAG|HEALTHCHECK_DATA
volumes:

View File

@ -67,4 +67,4 @@ CFG_SPEEDTEST_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_SPEEDTEST_PORT_1="speedtest-service|webui|random:80|public|tcp|false|true|true|Speedtest,Results|/,/results/stats.php"
CFG_SPEEDTEST_PORT_1="speedtest-service|webui|random:80|public|tcp|false|true|true|Speedtest,Results|/,/results/stats.php|speedtest"

View File

@ -22,13 +22,15 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.traefik-service-dashboard.entrypoints: web,websecure
traefik.http.routers.traefik-service-dashboard.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.traefik-service-dashboard.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.traefik-service-dashboard.service: api@internal
traefik.http.routers.traefik-service-dashboard.tls: true
traefik.http.routers.traefik-service-dashboard.tls.certresolver: production
traefik.http.routers.traefik-service-dashboard.tls.options: modern@file
traefik.http.routers.traefik-service-dashboard.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
traefik.docker.network: DOCKER_NETWORK_DATA #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
healthcheck:
disable: HEALTHCHECK_DATA #LIBREPORTAL|HEALTHCHECK_TAG|HEALTHCHECK_DATA

View File

@ -80,7 +80,7 @@ CFG_TRAEFIK_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_TRAEFIK_PORT_1="traefik-service|dashboard|random:8080|public|tcp|true|true|true|Admin Dashboard|"
CFG_TRAEFIK_PORT_1="traefik-service|dashboard|random:8080|public|tcp|true|true|true|Admin Dashboard||traefik"
CFG_TRAEFIK_PORT_2="traefik-service|https|443:443|public|tcp|false|false|false|HTTPS Traffic|"
CFG_TRAEFIK_PORT_3="traefik-service|http|80:80|disabled|tcp|false|false|false|HTTP Traffic|"

View File

@ -16,12 +16,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.trilium-service.entrypoints: web,websecure
traefik.http.routers.trilium-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.trilium-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.trilium-service.tls: true
traefik.http.routers.trilium-service.tls.certresolver: production
traefik.http.services.trilium-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.trilium-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.trilium-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
healthcheck:
disable: HEALTHCHECK_DATA #LIBREPORTAL|HEALTHCHECK_TAG|HEALTHCHECK_DATA
volumes:

View File

@ -59,4 +59,4 @@ CFG_TRILIUM_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_TRILIUM_PORT_1="trilium-service|webui|random:8080|private|tcp|false|true|true|Notes Interface|"
CFG_TRILIUM_PORT_1="trilium-service|webui|random:8080|private|tcp|false|true|true|Notes Interface||notes"

View File

@ -26,12 +26,14 @@ services:
libreportal.category: "CATEGORY_DATA" #LIBREPORTAL|CATEGORY_TAG|CATEGORY_DATA
libreportal.title: "TITLE_DATA" #LIBREPORTAL|TITLE_TAG|TITLE_DATA
traefik.enable: TRAEFIK_ENABLE_DATA #LIBREPORTAL|TRAEFIK_ENABLE_TAG|TRAEFIK_ENABLE_DATA
# TRAEFIK_PORT_1_BEGIN
traefik.http.routers.vaultwarden-service.entrypoints: web,websecure
traefik.http.routers.vaultwarden-service.rule: Host(`DOMAINSUBNAME_DATA`) #LIBREPORTAL|DOMAINSUBNAME_TAG|DOMAINSUBNAME_DATA
traefik.http.routers.vaultwarden-service.rule: Host(`DOMAINSUBNAME_DATA_1`) #LIBREPORTAL|DOMAINSUBNAME_TAG_1|DOMAINSUBNAME_DATA_1
traefik.http.routers.vaultwarden-service.tls: true
traefik.http.routers.vaultwarden-service.tls.certresolver: production
traefik.http.services.vaultwarden-service.loadbalancer.server.port: PORT_INTERNAL_DATA_1 #LIBREPORTAL|PORT_INTERNAL_TAG_1|PORT_INTERNAL_DATA_1
traefik.http.routers.vaultwarden-service.middlewares: MIDDLEWARE_DATA #LIBREPORTAL|MIDDLEWARE_TAG|MIDDLEWARE_DATA
traefik.http.routers.vaultwarden-service.middlewares: MIDDLEWARE_DATA_1 #LIBREPORTAL|MIDDLEWARE_TAG_1|MIDDLEWARE_DATA_1
# TRAEFIK_PORT_1_END
healthcheck:
disable: HEALTHCHECK_DATA #LIBREPORTAL|HEALTHCHECK_TAG|HEALTHCHECK_DATA
# GLUETUN_OFF_BEGIN

View File

@ -70,5 +70,5 @@ CFG_VAULTWARDEN_NETWORK=default
# - webui: if true, this port serves the main web interface
# - description: human-readable description of the service
#
CFG_VAULTWARDEN_PORT_1="vaultwarden-service|webui|8201:80|public|tcp|false|true|true|Password Manager Interface|"
CFG_VAULTWARDEN_PORT_1="vaultwarden-service|webui|8201:80|public|tcp|false|true|true|Password Manager Interface||vault"
CFG_VAULTWARDEN_PORT_2="vaultwarden-exporter|metrics|3001:3001|disabled|tcp|false|false|false|Metrics Exporter (sidecar, docker-network only)|"

View File

@ -11,6 +11,8 @@ appUpdateSpecifics()
if [[ $CFG_REQUIREMENT_DNS_UPDATER == "true" ]]; then
updateDNS $app_name install;
fi
# Split-horizon local DNS: app subdomains resolve to the box on the LAN.
declare -F setupLocalDnsRewrites >/dev/null 2>&1 && setupLocalDnsRewrites
fi
if [[ $app_name == "libreportal" ]]; then

View File

@ -9,4 +9,6 @@ appAdguardApplyDnsUpdater()
fi
updateDNS "adguard" "manual"
isSuccessful "/etc/resolv.conf updated to use AdGuard as the host DNS resolver."
# Split-horizon: make app subdomains resolve to the box on the LAN.
declare -F setupLocalDnsRewrites >/dev/null 2>&1 && setupLocalDnsRewrites
}

View File

@ -9,4 +9,6 @@ appPiholeApplyDnsUpdater()
fi
updateDNS "pihole" "manual"
isSuccessful "/etc/resolv.conf updated to use Pi-hole as the host DNS resolver."
# Split-horizon: make app subdomains resolve to the box on the LAN.
declare -F setupLocalDnsRewrites >/dev/null 2>&1 && setupLocalDnsRewrites
}

View File

@ -60,6 +60,15 @@ dockerConfigSetupFileWithData()
# and Authelia takes precedence when installed.
tagsProcessorPortMiddlewares "$full_file_path" "$app_name"
# Per-port subdomains (DOMAINSUBNAME_TAG_1, _2, ...). The dynamic
# replacement for the single static HOST_NAME — one host per
# Traefik-managed port, so a container can serve unlimited hosts.
tagsProcessorPortSubdomains "$full_file_path" "$app_name"
# Strip (comment out) router blocks for ports that aren't Traefik-managed,
# so an unfilled DOMAINSUBNAME_DATA_<n> placeholder can never ship.
tagsProcessorPortRouterBlocks "$full_file_path" "$app_name"
tagsProcessorTraefikControl "$full_file_path" "$public"
tagsManagerUpdateUniversalTag "$full_file_path" "DOMAINSUBNAME_TAG" "$host_setup"

View File

@ -11,11 +11,10 @@ setupDNSIP()
fi
fi
# Build variable names based on app_name
dns_host_name_var="CFG_${app_name^^}_HOST_NAME"
# Access the variables using variable indirection
dns_host_name="${!dns_host_name_var}"
# UNFINISHED
# STUB: meant to resolve the reachable IP of the given resolver
# (adguard/pihole) into $dns_ip_setup for updateDNS. Not implemented yet,
# so updateDNS falls back to CFG_DNS_SERVER_* upstreams. (Previously read
# CFG_<APP>_HOST_NAME here, which is unused — removed during the per-port
# subdomain refactor so HOST_NAME has no remaining DNS dependency.)
:
}

View File

@ -0,0 +1,140 @@
#!/bin/bash
#
# Split-horizon ("local") DNS.
#
# Points every configured domain at the LibrePortal server's LAN IP inside the
# self-hosted resolver, so app subdomains resolve to the box on the local
# network and hit Traefik directly — with valid Let's Encrypt certs — instead
# of bouncing out to the public IP (which most home routers can't hairpin).
#
# Domain-level, single-host model: every domain -> the one server IP. Traefik
# sorts out which app by Host header. Adding apps/domains later is covered
# automatically (AdGuard wildcard) or on the next run (Pi-hole host list).
#
# SAFE BY CONSTRUCTION: every action is idempotent, guarded by an "installed"
# check, and cannot corrupt the resolver if a detail is off —
# * AdGuard goes through its REST API; a bad URL/cred just fails harmlessly.
# * Pi-hole writes ONLY to the supported, mounted /etc/pihole/custom.list,
# inside a clearly-marked managed block (never touches /etc/dnsmasq.d).
# NOTE: the AdGuard API call and the Pi-hole reload need a live smoke-test —
# they can't be exercised without the running containers.
# The server's LAN IP (the source address used to reach the network).
localDnsServerIp() {
local ip
ip=$(ip -4 route get 1.1.1.1 2>/dev/null | awk '{for (i=1;i<=NF;i++) if ($i=="src") {print $(i+1); exit}}')
[[ -z "$ip" ]] && ip="${public_ip_v4:-}" # last-resort fallback
printf '%s' "$ip"
}
# Configured (non-empty) domains, one per line.
localDnsDomains() {
local i d
for i in 1 2 3 4 5 6 7 8 9; do
d="CFG_DOMAIN_${i}"; d="${!d:-}"
[[ -n "$d" ]] && printf '%s\n' "$d"
done
}
# Every app host (subdomain.domain) across all apps' Traefik-managed ports —
# for resolvers without wildcard support (Pi-hole custom.list). Mirrors the
# per-port host rule: subdomain ""/@/root -> apex, else <subdomain>.<domain>.
localDnsAppHosts() {
local cfg app up d_idx dom portv sub host
local -a parts
for cfg in "${containers_dir}"*/*.config; do
[[ -f "$cfg" ]] || continue
app=$(basename "$cfg" .config); up=${app^^}
d_idx=$(grep -oE "CFG_${up}_DOMAIN=[0-9]+" "$cfg" | head -1 | cut -d= -f2)
[[ -z "$d_idx" ]] && continue
dom="CFG_DOMAIN_${d_idx}"; dom="${!dom:-}"
[[ -z "$dom" ]] && continue
while IFS= read -r portv; do
IFS='|' read -ra parts <<< "$portv"
[[ "${parts[6]:-}" == "true" ]] || continue # Traefik-managed only
sub="${parts[10]:-}"
if [[ "$sub" == "@" || "$sub" == "root" ]]; then
host="$dom" # apex (explicit only)
elif [[ -n "$sub" ]]; then
host="${sub}.${dom}"
else
host="${app}.${dom}" # no subdomain set -> app-name default
fi
printf '%s\n' "$host"
done < <(grep -oE "CFG_${up}_PORT_[0-9]+=\"[^\"]*\"" "$cfg" | sed -E 's/^[^"]*"//; s/"$//')
done | sort -u
}
# AdGuard Home: wildcard rewrite per domain (covers every subdomain) + apex,
# via the REST API. Idempotent (delete-then-add). Admin port discovered at
# runtime via `docker port`, creds from the saved CFG_ADGUARD_* values.
localDnsApplyAdguard() {
local ip="$1"; shift
local user="${CFG_ADGUARD_ADMIN_USER:-admin}"
local pass="${CFG_ADGUARD_ADMIN_PASSWORD:-${CFG_ADGUARD_PASSWORD:-}}"
local hostport base d entry payload
hostport=$(dockerCommandRun "docker port adguard-service 3000/tcp" 2>/dev/null | head -1 | sed 's/.*://')
if [[ -z "$hostport" ]]; then
isNotice "AdGuard admin port not found (running?). Skipping AdGuard rewrites."
return 0
fi
base="http://127.0.0.1:${hostport}"
for d in "$@"; do
for entry in "*.${d}" "${d}"; do
payload="{\"domain\":\"${entry}\",\"answer\":\"${ip}\"}"
curl -fsS -u "${user}:${pass}" -H 'Content-Type: application/json' \
-X POST "${base}/control/rewrite/delete" -d "$payload" >/dev/null 2>&1
if curl -fsS -u "${user}:${pass}" -H 'Content-Type: application/json' \
-X POST "${base}/control/rewrite/add" -d "$payload" >/dev/null 2>&1; then
isSuccessful "AdGuard rewrite: ${entry} -> ${ip}"
else
isNotice "AdGuard rewrite for ${entry} not applied (check API URL/creds) — safe to retry."
fi
done
done
}
# Pi-hole: per-host A records in the mounted, supported custom.list, inside a
# managed block (no wildcards on Pi-hole; no touching /etc/dnsmasq.d). Reloads
# via `pihole restartdns`, falling back to a container restart.
localDnsApplyPihole() {
local ip="$1"
local list="${containers_dir}pihole/pihole-dnsmasq-unbound/custom.list" # mounts to /etc/pihole
local b="# >>> libreportal-local >>>" e="# <<< libreportal-local <<<"
local hosts tmp h n
hosts=$(localDnsAppHosts)
if [[ -z "$hosts" ]]; then isNotice "No app hosts for Pi-hole — skipping."; return 0; fi
tmp=$(sudo mktemp)
if [[ -f "$list" ]]; then # preserve anything outside our block
sudo awk -v b="$b" -v e="$e" '$0==b{skip=1} !skip{print} $0==e{skip=0}' "$list" | sudo tee "$tmp" >/dev/null
fi
{
echo "$b"
while IFS= read -r h; do [[ -n "$h" ]] && echo "${ip} ${h}"; done <<< "$hosts"
echo "$e"
} | sudo tee -a "$tmp" >/dev/null
sudo cp "$tmp" "$list"; sudo rm -f "$tmp"
n=$(printf '%s\n' "$hosts" | grep -c .)
dockerCommandRun "docker exec pihole-service pihole restartdns" >/dev/null 2>&1 || dockerComposeRestart pihole
isSuccessful "Pi-hole custom.list updated: ${n} hosts -> ${ip}"
}
# Orchestrator — call after a domain change or app install.
setupLocalDnsRewrites() {
isHeader "Local (split-horizon) DNS"
local ip domains
ip=$(localDnsServerIp)
[[ -z "$ip" ]] && { isNotice "Could not determine the server LAN IP — skipping local DNS."; return 0; }
domains=$(localDnsDomains)
[[ -z "$domains" ]] && { isNotice "No domains configured (CFG_DOMAIN_*) — skipping local DNS."; return 0; }
isNotice "Server IP ${ip} · domains: $(printf '%s ' $domains)"
local did=0
if [[ "$(dockerCheckAppInstalled "adguard" "docker")" == "installed" ]]; then
localDnsApplyAdguard "$ip" $domains; did=1
fi
if [[ "$(dockerCheckAppInstalled "pihole" "docker")" == "installed" ]]; then
localDnsApplyPihole "$ip"; did=1
fi
[[ "$did" -eq 0 ]] && isNotice "Neither AdGuard nor Pi-hole installed — local DNS skipped."
}

View File

@ -0,0 +1,98 @@
#!/bin/bash
# Per-port Traefik subdomain/host writer.
#
# Companion to traefik_port_middlewares.sh. Where that stamps a per-port
# MIDDLEWARE_TAG_<i>, this stamps a per-port DOMAINSUBNAME_TAG_<i> holding the
# fully-qualified host for that port's Traefik router, derived from the port's
# `subdomain` column (the 11th field of the 12-col PORT format).
#
# This is the dynamic replacement for the old static, per-app
# CFG_<APP>_HOST_NAME model: a single container can now expose any number of
# hosts — one per Traefik-managed port — instead of being limited to one.
#
# subdomain "" | "@" | "root" -> <domain> (apex / root of domain)
# subdomain "vault" -> vault.<domain> (single label)
# subdomain "admin.headscale" -> admin.headscale.<domain> (multi-level allowed)
#
# Index scheme matches traefik_port_middlewares.sh exactly: i walks every
# parsed port (0-based), idx = i+1 is the 1-based position used in the tag
# suffix, and only Traefik-managed ports (traefik=true) are stamped — so a
# port's MIDDLEWARE_TAG_<idx> and DOMAINSUBNAME_TAG_<idx> always line up on the
# same router.
tagsProcessorPortSubdomains()
{
local file="$1"
local app_name="$2"
if [[ -z "$file" || -z "$app_name" ]]; then
return 0
fi
local count=${#port_service_names[@]}
local i=0
while [[ $i -lt $count ]]; do
local idx=$((i + 1))
local p_traefik="${port_traefik_managed[$i]}"
local p_sub="${port_subdomains[$i]}"
if [[ "$p_traefik" == "true" ]]; then
local host
if [[ "$p_sub" == "@" || "$p_sub" == "root" ]]; then
host="${domain_full}" # apex / root of the domain (explicit only)
elif [[ -n "$p_sub" ]]; then
host="${p_sub}.${domain_full}" # subdomain (single or multi-level)
else
host="${app_name}.${domain_full}" # no subdomain set -> app-name default
fi
tagsManagerUpdateUniversalTag "$file" "DOMAINSUBNAME_TAG_${idx}" "$host"
fi
i=$((i + 1))
done
}
# Comments out the Traefik router block for any port that is NOT Traefik-managed
# (non-public, metrics-only, or a slot with no router at all), so an unfilled
# DOMAINSUBNAME_DATA_<n> placeholder can never reach a live compose. Each router
# is wrapped in # TRAEFIK_PORT_<n>_BEGIN ... # TRAEFIK_PORT_<n>_END markers;
# this mirrors the GLUETUN_OFF region-commenting in tags_processor_network_mode.sh.
tagsProcessorPortRouterBlocks()
{
local file="$1"
local app_name="$2"
if [[ -z "$file" || ! -f "$file" ]]; then
return 0
fi
# Space-padded list of 1-based indices of Traefik-managed ports, e.g. " 1 3 ".
local active=" "
local count=${#port_service_names[@]}
local i=0
while [[ $i -lt $count ]]; do
[[ "${port_traefik_managed[$i]}" == "true" ]] && active+="$((i + 1)) "
i=$((i + 1))
done
local tmp="${file}.routers.$$"
sudo awk -v active="$active" '
BEGIN { off = 0 }
/#[[:space:]]*TRAEFIK_PORT_[0-9]+_BEGIN/ {
match($0, /TRAEFIK_PORT_[0-9]+/); key = substr($0, RSTART, RLENGTH)
sub(/TRAEFIK_PORT_/, "", key)
off = (index(active, " " key " ") > 0) ? 0 : 1 # off=1 -> comment the block
print; next
}
/#[[:space:]]*TRAEFIK_PORT_[0-9]+_END/ { off = 0; print; next }
{
if (off == 1 && $0 !~ /^[[:space:]]*#/) {
match($0, /^[[:space:]]*/)
indent = substr($0, RSTART, RLENGTH)
rest = substr($0, RLENGTH + 1)
print indent "# " rest
next
}
print
}
' "$file" | sudo tee "$tmp" >/dev/null
sudo mv "$tmp" "$file"
}

View File

@ -35,7 +35,16 @@ initializeAppVariables()
app_title="${!app_title_var}"
domain_var_name="CFG_DOMAIN_${domain}"
domain_full="${!domain_var_name}"
host_setup=${app_name}.${domain_full}
# FQDN for this app's Traefik Host() rule (also feeds the app URL and
# trusted-domains):
# HOST_NAME="@" or "root" -> <domain> (apex / root of domain)
# HOST_NAME set -> <HOST_NAME>.<domain> (custom subdomain)
# HOST_NAME empty -> <app_name>.<domain> (fallback default)
if [[ "$host_name" == "@" || "$host_name" == "root" ]]; then
host_setup="${domain_full}"
else
host_setup="${host_name:-$app_name}.${domain_full}"
fi
ssl_key=${domain_full}.key
ssl_crt=${domain_full}.crt

View File

@ -16,6 +16,7 @@ network_scripts=(
"network/display/show_traefik_services.sh"
"network/dns/setup_dns_ip.sh"
"network/dns/setup_dns.sh"
"network/dns/setup_local_dns.sh"
"network/firewall/firewall_initial_setup.sh"
"network/firewall/rules/firewall_clear_rules.sh"
"network/firewall/rules/firewall_rebuild_from_db.sh"
@ -38,6 +39,7 @@ network_scripts=(
"network/traefik/traefik_login_credentials.sh"
"network/traefik/traefik_middlewares.sh"
"network/traefik/traefik_port_middlewares.sh"
"network/traefik/traefik_port_subdomains.sh"
"network/traefik/traefik_whitelist.sh"
"network/variables/basic_scan.sh"
"network/variables/headscale_variables.sh"

View File

@ -83,8 +83,8 @@ webuiCreateAppFieldMappings() {
"category": "network",
"label": "Hostname",
"type": "text",
"tooltip": "The hostname for this application",
"placeholder": "myapp"
"tooltip": "Subdomain this app is served on — e.g. myapp becomes myapp.yourdomain.com. Use @ to serve it on the root of your domain (yourdomain.com itself).",
"placeholder": "myapp · @ = root domain"
},
"DOMAIN": {
"category": "network",

6
site/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
node_modules/
dist/
# generated from the repo at build time (npm run data)
src/_data/apps.json
src/_data/categories.json
*.bak

12
site/eleventy.config.cjs Normal file
View File

@ -0,0 +1,12 @@
module.exports = function (eleventyConfig) {
// copy static assets straight through to the build output
eleventyConfig.addPassthroughCopy({ "src/assets": "assets" });
eleventyConfig.addWatchTarget("src/assets");
return {
dir: { input: "src", includes: "_includes", data: "_data", output: "dist" },
htmlTemplateEngine: "njk",
markdownTemplateEngine: "njk",
templateFormats: ["njk", "html", "md"],
};
};

1522
site/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

15
site/package.json Normal file
View File

@ -0,0 +1,15 @@
{
"name": "libreportal-site",
"version": "0.1.0",
"private": true,
"description": "LibrePortal marketing/get site — data-driven from the repo via Eleventy.",
"scripts": {
"data": "node scripts/gen-data.mjs",
"build": "npm run data && eleventy",
"start": "npm run data && eleventy --serve --port 8777",
"clean": "rm -rf dist"
},
"devDependencies": {
"@11ty/eleventy": "^3.1.5"
}
}

78
site/scripts/gen-data.mjs Normal file
View File

@ -0,0 +1,78 @@
#!/usr/bin/env node
/*
* gen-data.mjs single source of truth: the LibrePortal repo.
*
* Reads every containers/<app>/<app>.config METADATA block and emits
* src/_data/apps.json (array of apps, used by the app grid)
* src/_data/categories.json (categories present, with friendly names + counts)
*
* Run via `npm run data` (also runs automatically before `npm run build`).
* Add an app to the repo -> rebuild -> the website updates itself.
*/
import { readdirSync, readFileSync, existsSync, writeFileSync, mkdirSync, statSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, join, resolve } from 'node:path';
const here = dirname(fileURLToPath(import.meta.url));
const repoRoot = resolve(here, '..', '..'); // site/scripts -> repo root
const containersDir = join(repoRoot, 'containers');
const dataDir = join(here, '..', 'src', '_data');
const iconsDir = join(here, '..', 'src', 'assets', 'apps');
// Only these metadata fields are pulled from each .config. LONG_DESCRIPTION must
// precede DESCRIPTION in the alternation so it wins the match.
const FIELD_RE = /^CFG_.+?_(LONG_DESCRIPTION|DESCRIPTION|CATEGORY|TITLE|URL)\s*=\s*"?(.*?)"?\s*$/;
const CATEGORY_NAMES = {
recommended: 'Recommended', communication: 'Communication', development: 'Development',
knowledge: 'Knowledge', media: 'Media', monitoring: 'Monitoring', storage: 'Storage',
network: 'Network', security: 'Security', productivity: 'Productivity', finance: 'Finance',
ai: 'AI', utilities: 'Utilities', privacy: 'Privacy', social: 'Social', system: 'System',
};
const titleCase = (s) => s.replace(/[-_]/g, ' ').replace(/\b\w/g, (m) => m.toUpperCase());
function parseConfig(text) {
const out = {};
for (const raw of text.split(/\r?\n/)) {
const m = FIELD_RE.exec(raw.trim());
if (m && out[m[1]] === undefined) out[m[1]] = m[2];
}
return out;
}
const apps = [];
for (const slug of readdirSync(containersDir)) {
const dir = join(containersDir, slug);
if (!statSync(dir).isDirectory()) continue;
const cfg = join(dir, `${slug}.config`);
if (!existsSync(cfg)) continue;
const meta = parseConfig(readFileSync(cfg, 'utf8'));
if (!meta.TITLE) continue; // skip anything without a display title (infra without metadata)
const cats = (meta.CATEGORY || 'utilities').split(',').map((s) => s.trim()).filter(Boolean);
apps.push({
slug,
title: meta.TITLE,
category: cats[0], // primary category
categories: cats, // an app can belong to several
description: meta.DESCRIPTION || '',
longDescription: meta.LONG_DESCRIPTION || meta.DESCRIPTION || '',
url: meta.URL || '',
icon: existsSync(join(iconsDir, `${slug}.svg`)) ? `assets/apps/${slug}.svg` : 'assets/apps/default.svg',
});
}
apps.sort((a, b) => a.title.localeCompare(b.title));
const catMap = new Map();
for (const a of apps) {
for (const cat of a.categories) {
const c = catMap.get(cat) || { id: cat, name: CATEGORY_NAMES[cat] || titleCase(cat), count: 0 };
c.count++;
catMap.set(cat, c);
}
}
const categories = [...catMap.values()].sort((a, b) => b.count - a.count || a.name.localeCompare(b.name));
mkdirSync(dataDir, { recursive: true });
writeFileSync(join(dataDir, 'apps.json'), JSON.stringify(apps, null, 2) + '\n');
writeFileSync(join(dataDir, 'categories.json'), JSON.stringify(categories, null, 2) + '\n');
console.log(`${apps.length} apps across ${categories.length} categories → src/_data/{apps,categories}.json`);

12
site/src/_data/site.json Normal file
View File

@ -0,0 +1,12 @@
{
"name": "LibrePortal",
"tagline": "your own private corner of the universe",
"version": "v0.1.0",
"installUrl": "https://get.libreportal.org",
"installCmd": "bash <(curl -fsSL https://get.libreportal.org) init",
"repo": "https://gitea.scottwebstar.co.uk/Webstar/LibrePortal",
"promiseUrl": "https://gitea.scottwebstar.co.uk/Webstar/LibrePortal/raw/branch/main/PROMISE.md",
"contributingUrl": "https://gitea.scottwebstar.co.uk/Webstar/LibrePortal/raw/branch/main/CONTRIBUTING.md",
"initUrl": "https://gitea.scottwebstar.co.uk/Webstar/LibrePortal/raw/branch/main/init.sh",
"inspiration": "https://gitlab.com/bmcgonag/docker_installs"
}

View File

@ -0,0 +1,10 @@
<article class="app-card glass" data-cats="{{ app.categories | join(' ') }}">
<div class="app-card-head">
<img class="app-ico" src="{{ app.icon }}" alt="" loading="lazy" width="42" height="42">
<div>
<h3>{{ app.title }}</h3>
<span class="app-cat">{{ app.category }}</span>
</div>
</div>
<p>{{ app.description }}</p>
</article>

View File

@ -0,0 +1,26 @@
<footer>
<div class="wrap">
<div class="foot-grid">
<div style="max-width:300px">
<a class="libreportal-logo" href="#top"><img src="assets/libreportal.svg" alt="" width="32" height="32">Libre<b>Portal</b></a>
<p style="color:var(--text-faint);font-size:.92rem">Your own private corner of the internet — free, open, and yours.</p>
</div>
<div class="foot-col">
<h4>Project</h4>
<a href="{{ site.repo }}" target="_blank" rel="noopener">Source code</a>
<a href="{{ site.promiseUrl }}" target="_blank" rel="noopener">The Promise</a>
<a href="{{ site.contributingUrl }}" target="_blank" rel="noopener">Contributing</a>
</div>
<div class="foot-col">
<h4>Get started</h4>
<a href="#install">Install</a>
<a href="#apps">Browse apps</a>
<a href="#connect">LibrePortal Connect</a>
</div>
</div>
<div class="colophon">
<span>Built from scratch since 2023 · inspired by <a href="{{ site.inspiration }}" target="_blank" rel="noopener">bmcgonag/docker_installs</a></span>
<span>GNU AGPLv3 · what's open stays open 🕊️</span>
</div>
</div>
</footer>

View File

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en" data-theme="nebula">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ site.name }} — {{ site.tagline }}</title>
<meta name="description" content="LibrePortal is a free, open, self-hosted app platform. One command brings up the apps you rely on — on your own server, with your data staying yours.">
<link rel="icon" type="image/svg+xml" href="assets/libreportal.svg">
<link rel="icon" href="assets/favicon.ico" sizes="any">
<link rel="stylesheet" href="assets/style.css">
</head>
<body>
<div class="cosmos"></div>
<div class="stars"></div>
{% include "topbar.njk" %}
{{ content | safe }}
{% include "footer.njk" %}
<script src="assets/main.js" defer></script>
</body>
</html>

View File

@ -0,0 +1,31 @@
<div class="topbar">
<button class="mobile-menu-toggle" id="mobile-menu-toggle" aria-label="Toggle navigation menu">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>
</button>
<div class="topbar-left">
<a class="libreportal-logo" href="#top"><img src="assets/libreportal.svg" alt="LibrePortal" width="32" height="32">Libre<b>Portal</b></a>
</div>
<div class="mobile-drawer" id="mobile-drawer">
<nav class="topbar-nav">
<a href="#top" class="nav-item nav-active" data-spy="top">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 11l9-8 9 8"/><path d="M5 10v10h14V10"/></svg>Home
</a>
<a href="#features" class="nav-item" data-spy="features">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg>Features
</a>
<a href="#apps" class="nav-item" data-spy="apps">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="4"/><path d="M12 2v3M12 19v3M2 12h3M19 12h3M5 5l2 2M17 17l2 2M19 5l-2 2M7 17l-2 2"/></svg>Apps
</a>
<a href="#connect" class="nav-item" data-spy="connect">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10Z"/></svg>Privacy
</a>
<a href="#promise" class="nav-item" data-spy="promise">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10Z"/><path d="M9 11l2 2 4-4"/></svg>Promise
</a>
</nav>
<div class="topbar-controls">
<a class="tb-ghost" href="{{ site.repo }}" target="_blank" rel="noopener">Source ↗</a>
<a class="tb-cta" href="#install">Install</a>
</div>
</div>
</div>

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><path d="M505.8 58.8C428.2 18.4 334.1 0 256 0h-.3v511.8c-21.5-12.7-41.1-26-59.1-39.6 18 13.7 37.8 27 59.4 39.8C506.8 363.4 505.8 146 505.8 58.8" style="fill-rule:evenodd;clip-rule:evenodd;fill:#68bc71"/><path d="M255.7 511.8C5.2 363.3 6.2 146 6.2 58.8 83.7 18.4 177.7 0 255.7 0z" style="fill-rule:evenodd;clip-rule:evenodd;fill:#67b279"/><path d="m246.9 341.6 151-203.6c-11.1-8.9-20.8-2.6-26.1 2.2h-.2l-125.9 131-47.4-57.1c-22.6-26.2-53.4-6.2-60.6-.9z" style="fill-rule:evenodd;clip-rule:evenodd;fill:#fff"/></svg>

After

Width:  |  Height:  |  Size: 598 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><linearGradient id="authelia_svg__a" x1="-7.464" x2="485.846" y1="532.755" y2="535.394" gradientTransform="translate(0 -278)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#3f51b4"/><stop offset="1" style="stop-color:#123156"/></linearGradient><path d="M256.7 128c67.4-1.9 128.3 52.3 128.6 127.9.3 72.7-58.1 128.6-129.3 128.5-70.2-.1-128.5-58.2-128-128.5.4-74.2 61.9-130.2 128.7-127.9m33.3 77.4c0-16.3-9.6-29.3-24.7-33.2-14.8-3.8-30.2 2.8-37.7 16-7.8 13.9-5.6 29.4 6.8 40.6 5.7 5.1 6.7 9.9 4.8 16.9-5.7 21.9-10.9 43.9-16.2 65.9-2 8.4.3 15.4 7.1 20.6 13.3 10.3 34.4 11.4 48.9 2.8 10.7-6.4 13.9-12.9 11.1-25-5.2-22.6-10.7-45.1-16.3-67.5-1.3-5.1-.7-8.4 3.8-11.9 7.9-6.3 13-14.5 12.4-25.2" style="fill:url(#authelia_svg__a)"/><linearGradient id="authelia_svg__b" x1="-7.511" x2="485.799" y1="541.56" y2="544.198" gradientTransform="translate(0 -278)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#3f51b4"/><stop offset="1" style="stop-color:#123156"/></linearGradient><path d="M254.9 447.7C163.1 450.2 76.7 380.2 65 279.1c-7.6-65.8 12.4-122.5 62-167.3 11.8-10.7 26.3-18.7 40.1-27 9.8-5.9 18.6-3 23.9 5.9 5.4 9.3 3.1 17.8-6.7 24.5-9.7 6.7-20.1 12.6-29.1 20.2-32.7 27.4-50.9 62.7-54.9 105.1-3.6 38.7 5 74.9 28.2 106.3C158.8 387.9 200 410 251.3 412c45.7 1.7 85.1-14.5 116.6-46.9 12.8-13.2 21.7-30.3 31.8-46.1 5.4-8.5 12.7-13 20.8-10.9 11.2 3 17.2 12.7 11.9 23.9-7.2 15.2-15.2 30.6-25.6 43.7-33.4 42.1-78 65-131.1 71.7-.8.1-1.5.2-2.3.2-6.2.1-12.4.1-18.5.1" style="fill:url(#authelia_svg__b)"/><linearGradient id="authelia_svg__c" x1="-7.285" x2="486.025" y1="499.335" y2="501.973" gradientTransform="translate(0 -278)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#3f51b4"/><stop offset="1" style="stop-color:#123156"/></linearGradient><path d="M226.6 4.5c4.1 0 8.2.1 12.3 0 7.4-.1 13.2 2 15 10.2 1.7 7.7-1.7 16.9-8.5 19.7-5.3 2.2-11.3 3.2-17.1 4-41.8 5.5-79.6 20.8-112 47.8C71 124 43.4 172 36.9 231.2c-6.4 58.4 8.9 111 43.5 158.1 5.6 7.6 12.4 14.4 18.2 22 6.8 8.8 5.7 17-2.6 24.5-6.9 6.3-16.4 6.1-23.5-1.2-42-43.2-66.3-94.5-71.4-154.9-2.2-26.1-1.2-51.8 4.1-77.4 8.1-39 25.1-73.9 49.8-104.9 39-48.8 89.4-79.6 150.9-91.7 6.7-1.3 13.8-1.1 20.7-1.6z" style="fill:url(#authelia_svg__c)"/><linearGradient id="authelia_svg__d" x1="-7.857" x2="485.453" y1="606.3" y2="608.938" gradientTransform="translate(0 -278)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#3f51b4"/><stop offset="1" style="stop-color:#123156"/></linearGradient><path d="M282.8 507.8c-2.8 0-5.7.2-8.5 0-9.2-.8-15.5-6.5-16.4-14.6-1-8.7 4.4-16.6 13.7-18.8 7.2-1.7 14.7-2.4 22-3.7 68.3-12.6 120-48.6 154.5-109.2C466 330 475.4 295.9 476.3 260c.7-27.3-3.7-54.3-13.8-80.1-1.6-4-2.5-9.2-1.4-13.2 2.1-7.5 7.2-13.1 15.8-13.8 8-.6 14.9 3 17.9 11.8 4.9 14.3 9.7 28.8 12.5 43.7 10 53.6 4.1 105.5-19.3 155-19.1 40.2-46.7 73.6-83.1 99.5-32.4 23-68.1 38.1-107.5 44.1-1.8.3-3.5.8-5.3.9-3.1 0-6.2-.1-9.3-.1" style="fill:url(#authelia_svg__d)"/><linearGradient id="authelia_svg__e" x1="-6.927" x2="486.383" y1="432.424" y2="435.062" gradientTransform="translate(0 -278)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#3f51b4"/><stop offset="1" style="stop-color:#123156"/></linearGradient><path d="M444.5 215.5c0 11.9-5.2 18.6-14.3 20.3-8.8 1.6-16.2-2.9-19.6-12.3-4.5-12.3-8.1-25-13.6-36.8-14.9-32.2-39.1-55.6-70.8-71.3-2.8-1.4-5.6-2.6-8.2-4.2-8.4-5.2-11.6-14.9-7.8-23.4 4-9 12.9-13.8 22.3-9.2 14.5 7 29 14.6 41.8 24.3 34.8 26.3 57.1 61.4 68.5 103.4.9 3.7 1.4 7.5 1.7 9.2" style="fill:url(#authelia_svg__e)"/></svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><path d="m218.5 367 288.3-166.5v-63.4L403.9 77.7l-9.4-5.4-93.7-54.1L12.5 184.7c-13.6 24 0 63.4 0 63.4-16.8 25.5 0 63.4 0 63.4l206 118.9 182.8-105.5-182.8 105.6-206-118.9c-16.8 25.5 0 63.4 0 63.4l206 118.9 288.3-166.5V264l.1-.1v-63.4z" style="fill-rule:evenodd;clip-rule:evenodd;fill:#fff"/><path d="M218.5 496.3q-.6 0-1.2-.3l-206-119c-.4-.3-.8-.6-1-1.1-.7-1.6-17.1-39.4.2-65.7.7-1.1 2.1-1.4 3.2-.8l204.8 118.2 287.1-165.8c.7-.4 1.7-.4 2.4 0s1.2 1.2 1.2 2.1v63.4c0 .9-.5 1.6-1.2 2.1L219.7 495.9c-.3.3-.8.4-1.2.4m-204.1-123 204.1 117.8L504.4 326v-57.9L219.7 432.5c-.7.4-1.7.4-2.4 0l-204-117.7c-12.7 22.2-.9 53.4 1.1 58.5M218.5 306q-.6 0-1.2-.3l-206-118.9c-.7-.4-1.2-1.2-1.2-2.1s.5-1.6 1.2-2.1L299.6 16.1c.7-.4 1.7-.4 2.4 0L508 135c.7.4 1.2 1.2 1.2 2.1s-.5 1.6-1.2 2.1L219.7 305.6c-.3.3-.8.4-1.2.4M17.3 184.7l201.2 116.1L502 137.1 300.8 20.9zm201.2 184.7q-.6 0-1.2-.3l-206-118.9c-.5-.3-.9-.7-1.1-1.3-.6-1.7-13.8-40.7.2-65.4.3-.6.8-1 1.5-1.1.6-.2 1.3-.1 1.8.2l204.8 118.2L505.6 135c.7-.4 1.7-.4 2.4 0s1.2 1.2 1.2 2.1v63.4c0 .9-.5 1.6-1.2 2.1L219.7 369c-.3.3-.8.4-1.2.4m-204-123 204 117.7L504.4 199v-57.9L219.7 305.6c-.7.4-1.7.4-2.4 0L13.5 188c-10.1 21-.7 52.9 1 58.4m204 186.4q-.6 0-1.2-.3l-206-118.9c-.4-.3-.8-.6-1-1.1-.7-1.6-17.1-39.4.2-65.7.7-1.1 2.1-1.4 3.2-.8l204.8 118.2 287.2-165.7c.7-.4 1.7-.4 2.4 0s1.2 1.2 1.2 2.1V264c0 .9-.5 1.7-1.2 2.1L219.7 432.4c-.3.3-.8.4-1.2.4m-204.1-123 204.1 117.8 286-165v-57.9L219.7 369c-.7.4-1.7.4-2.4 0l-204-117.7c-12.7 22.2-.9 53.4 1.1 58.5m265.9-158.4c-.3 0-.6-.1-.9-.2-.7-.3-1.2-.9-1.4-1.6l-6.5-26-46.4-3.9c-1-.1-1.9-.8-2.1-1.9-.2-1 .2-2.1 1.1-2.6l123.6-71.3c.7-.4 1.7-.4 2.4 0l55 31.7a2.438 2.438 0 0 1 0 4.2L281.5 151c-.3.3-.8.4-1.2.4m-47.1-35.9 40.5 3.4c1 .1 1.9.8 2.1 1.8l6.1 24.6 117.2-67.6-50.2-28.9z" style="fill:#0288d1"/></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,32 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" fill="none">
<!-- Shield silhouette -->
<path d="M64 8 L112 24 V60 C112 86 92 110 64 120 C36 110 16 86 16 60 V24 Z"
fill="url(#cs-grad)" stroke="#5dd3ff" stroke-width="2.5" stroke-linejoin="round"/>
<defs>
<linearGradient id="cs-grad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#1a2b3d"/>
<stop offset="1" stop-color="#0a1420"/>
</linearGradient>
<radialGradient id="cs-eye" cx="0.5" cy="0.5" r="0.5">
<stop offset="0" stop-color="#5dd3ff"/>
<stop offset="0.5" stop-color="#2b8fc7"/>
<stop offset="1" stop-color="#0a3554"/>
</radialGradient>
</defs>
<!-- Eye (almond) -->
<path d="M30 64 Q64 38 98 64 Q64 90 30 64 Z"
fill="#0a1420" stroke="#5dd3ff" stroke-width="2.2" stroke-linejoin="round"/>
<!-- Iris -->
<circle cx="64" cy="64" r="14" fill="url(#cs-eye)"/>
<!-- Pupil -->
<circle cx="64" cy="64" r="6" fill="#06121b"/>
<!-- Highlight -->
<circle cx="60" cy="60" r="2.4" fill="#dffaff" opacity="0.9"/>
<!-- Crosshair ticks signalling watcher/detector -->
<g stroke="#5dd3ff" stroke-width="2" stroke-linecap="round">
<line x1="64" y1="42" x2="64" y2="48"/>
<line x1="64" y1="80" x2="64" y2="86"/>
<line x1="42" y1="64" x2="48" y2="64"/>
<line x1="80" y1="64" x2="86" y2="64"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 90 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><rect width="512" height="512" rx="96" fill="#3a4a5a"/><path d="M256 116 416 200v112L256 396 96 312V200z" fill="none" stroke="#cdd6df" stroke-width="28" stroke-linejoin="round"/><path d="M96 200l160 84 160-84M256 284v112" fill="none" stroke="#cdd6df" stroke-width="28" stroke-linejoin="round" stroke-linecap="round"/></svg>

After

Width:  |  Height:  |  Size: 386 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><path d="m346 92-5.7-25.8L374.6 0l21 35.4 41.1-1.4-37.1 64.6-26.4 9.8-74 135.4c8.4 9.7 12.4 23.1 7.7 36.9-6.9 20.3-29.5 30.9-50.5 23.8s-32.5-29.3-25.7-49.6c4.6-13.6 16.3-22.9 29.9-25.4 3.4-.7 6.9-.8 10.3-.5zm37.9 41.6-3.7 39.1c37.2 39.3 53.9 95.9 34.7 152.5-27 79.8-116 121.7-198.9 93.7-82.8-28-128.1-115.4-101.1-195.2 23.9-70.6 96.4-110.2 166.6-101.4L310.4 97C208.7 69.2 93.1 123.5 56 233.1 18.6 343.6 77.8 463.4 188.3 500.8 298.7 538.2 418.6 479 456 368.5c30.5-90.2-3.8-182.3-72.1-234.9m-225.6 98.3c-10 29.4-6.6 60.2 6.8 86.2 13.4 25.8 36.7 46.9 66.9 57.1s61.5 7.7 87.8-4.7c26.5-12.5 47.8-34.9 57.8-64.3 6.3-18.7 7.2-37.2 3.9-54.5-4-20.8-14.1-39.8-28.2-55.2-1.4-1.6-2.9-3.1-4.4-4.6l-8.2 41c4.5 7.7 7.7 16 9.4 24.8 2.3 12.1 1.7 25.1-2.8 38.2-7.1 20.9-22.3 36.8-41.2 45.7-19.1 9-41.9 10.8-63.9 3.3s-39.1-22.8-48.8-41.5c-9.6-18.5-12-40.4-5-61.3 4.7-13.8 12.8-25.4 23.3-34.2 10.9-9.3 24.3-15.5 38.6-18.1h.2c2.4-.5 4.7-.8 7.1-1l28.8-30.2c-13.6-2.6-27.7-2.9-41.9-.1-19.9 3.6-38.4 12.3-53.5 25.1-14.5 12.4-26.1 28.8-32.7 48.3" style="fill:#1c58d9"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512">
<path d="M414.4 376.5 200 379.6l-1.4-256.7 103.5-15.2 108.8-1.5z" style="fill:#fff"/>
<path d="M502.6 103.7c-3.3-3.3-7.8-3.3-7.8-3.3s-95.5 5.4-144.9 6.5c-10.8.2-21.6.5-32.3.6V203c-4.5-2.1-9-4.3-13.5-6.4 0-29.6-.1-88.9-.1-88.9-23.6.3-72.7-1.8-72.7-1.8s-115.2-5.8-127.7-6.9c-8-.5-18.3-1.7-31.8 1.2-7.1 1.5-27.3 6-43.8 21.9C-8.7 154.8.7 206.7 1.9 214.5c1.4 9.5 5.6 36 25.8 59 37.3 45.7 117.6 44.6 117.6 44.6s9.9 23.5 24.9 45.2c20.4 27 41.3 48 61.7 50.5 51.3 0 153.9-.1 153.9-.1s9.8.1 23-8.4c11.4-6.9 21.6-19.1 21.6-19.1s10.5-11.2 25.2-36.9c4.5-7.9 8.2-15.6 11.5-22.8 0 0 45-95.4 45-188.2-1-28-7.9-33-9.5-34.6M97.7 269.9c-21.1-6.9-30.1-15.2-30.1-15.2S52 243.8 44.2 222.3c-13.4-36-1.1-58-1.1-58s6.8-18.3 31.4-24.4c11.2-3 25.2-2.5 25.2-2.5s5.8 48.4 12.8 76.7c5.9 23.8 20.2 63.3 20.2 63.3s-21.3-2.6-35-7.5m289.4-4.5c-5.2 12.6-44.8 92.1-44.8 92.1s-5 11.8-16 12.5c-4.7.3-8.4-1-8.4-1s-.2-.1-4.3-1.7l-92-44.8s-8.9-4.6-10.4-12.7c-1.8-6.6 2.2-14.7 2.2-14.7l44.2-91.1s3.9-7.9 9.9-10.6c.5-.2 1.9-.8 3.7-1.2 6.6-1.7 14.7 2.3 14.7 2.3l18.4 8.9c-3.7 7.6-7.5 15.2-11.2 22.9-5.5-.1-10.5 2.9-13.1 7.7-2.8 5.1-2.2 11.5 1.5 16.1-6.6 13.8-13.3 27.5-19.9 41.1-6.7.1-12.5 4.7-14.1 11.2-1.5 6.5 1.6 13.3 7.4 16.3 6.3 3.3 14.3 1.5 18.5-4.4 4.2-5.8 3.5-13.8-1.5-18.8l19.5-40c1.2.1 3 .2 5-.4 3.3-.7 5.8-2.9 5.8-2.9 3.4 1.5 7 3.1 10.8 5 3.9 2 7.6 4 10.9 5.9.7.4 1.5.9 2.3 1.5 1.3 1.1 2.8 2.5 3.8 4.5 1.5 4.5-1.5 12.1-1.5 12.1-1.9 6.2-15 33.1-15 33.1-6.6-.2-12.5 4.1-14.4 10.2-2.1 6.6.9 14.1 7.2 17.3 6.4 3.3 14.2 1.4 18.3-4.3 4.1-5.5 3.7-13.3-.9-18.4l4.6-9.2c4.1-8.5 11-24.8 11-24.8.7-1.4 4.6-8.4 2.2-17.3-2-9.3-10.3-13.6-10.3-13.6-9.9-6.4-23.8-12.4-23.8-12.4s0-3.3-.9-5.8-2.3-4.2-3.2-5.1c3.6-7.6 7.4-15.1 11-22.6l61.8 29.9s10.3 4.6 12.5 13.2c1.5 6-.4 11.4-1.5 14" style="fill:#609926"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
<defs>
<linearGradient id="g" x1="0" y1="0" x2="64" y2="64" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#22d3ee"/>
<stop offset="1" stop-color="#6366f1"/>
</linearGradient>
</defs>
<path d="M32 4 L56 13 V32 C56 46 45 56 32 60 C19 56 8 46 8 32 V13 Z"
fill="url(#g)" stroke="#0ea5e9" stroke-width="2" stroke-linejoin="round"/>
<path d="M22 30 C26 24 38 24 42 30 M25 35 C28 31 36 31 39 35 M29 40 C30 38 34 38 35 40"
stroke="#ffffff" stroke-width="2.5" stroke-linecap="round" fill="none"/>
<circle cx="32" cy="44" r="2.2" fill="#ffffff"/>
</svg>

After

Width:  |  Height:  |  Size: 678 B

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 142.5 145.6" style="enable-background:new 0 0 142.5 145.6;" xml:space="preserve">
<style type="text/css">
.st0{fill:#565656;}
.st1{fill:url(#SVGID_1_);}
</style>
<g>
<path class="st0" d="M28.7,131.5c-0.3,7.9-6.6,14.1-14.4,14.1C6.1,145.6,0,139,0,130.9s6.6-14.7,14.7-14.7c3.6,0,7.2,1.6,10.2,4.4
l-2.3,2.9c-2.3-2-5.1-3.4-7.9-3.4c-5.9,0-10.8,4.8-10.8,10.8c0,6.1,4.6,10.8,10.4,10.8c5.2,0,9.3-3.8,10.2-8.8H12.6v-3.5h16.1
V131.5z"/>
<path class="st0" d="M42.3,129.5h-2.2c-2.4,0-4.4,2-4.4,4.4v11.4h-3.9v-19.6H35v1.6c1.1-1.1,2.7-1.6,4.6-1.6h4.2L42.3,129.5z"/>
<path class="st0" d="M63.7,145.3h-3.4v-2.5c-2.6,2.5-6.6,3.7-10.7,1.9c-3-1.3-5.3-4.1-5.9-7.4c-1.2-6.3,3.7-11.9,9.9-11.9
c2.6,0,5,1.1,6.7,2.8v-2.5h3.4V145.3z M59.7,137c0.9-4-2.1-7.6-6-7.6c-3.4,0-6.1,2.8-6.1,6.1c0,3.8,3.3,6.7,7.2,6.1
C57.1,141.2,59.1,139.3,59.7,137z"/>
<path class="st0" d="M71.5,124.7v1.1h6.2v3.4h-6.2v16.1h-3.8v-20.5c0-4.3,3.1-6.8,7-6.8h4.7l-1.6,3.7h-3.1
C72.9,121.6,71.5,123,71.5,124.7z"/>
<path class="st0" d="M98.5,145.3h-3.3v-2.5c-2.6,2.5-6.6,3.7-10.7,1.9c-3-1.3-5.3-4.1-5.9-7.4c-1.2-6.3,3.7-11.9,9.9-11.9
c2.6,0,5,1.1,6.7,2.8v-2.5h3.4v19.6H98.5z M94.5,137c0.9-4-2.1-7.6-6-7.6c-3.4,0-6.1,2.8-6.1,6.1c0,3.8,3.3,6.7,7.2,6.1
C92,141.2,93.9,139.3,94.5,137z"/>
<path class="st0" d="M119.4,133.8v11.5h-3.9v-11.6c0-2.4-2-4.4-4.4-4.4c-2.5,0-4.4,2-4.4,4.4v11.6h-3.9v-19.6h3.2v1.7
c1.4-1.3,3.3-2,5.2-2C115.8,125.5,119.4,129.2,119.4,133.8z"/>
<path class="st0" d="M142.4,145.3h-3.3v-2.5c-2.6,2.5-6.6,3.7-10.7,1.9c-3-1.3-5.3-4.1-5.9-7.4c-1.2-6.3,3.7-11.9,9.9-11.9
c2.6,0,5,1.1,6.7,2.8v-2.5h3.4v19.6H142.4z M138.4,137c0.9-4-2.1-7.6-6-7.6c-3.4,0-6.1,2.8-6.1,6.1c0,3.8,3.3,6.7,7.2,6.1
C135.9,141.2,137.8,139.3,138.4,137z"/>
</g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="71.25" y1="10.4893" x2="71.25" y2="113.3415" gradientTransform="matrix(1 0 0 -1 0 148.6)">
<stop offset="0" style="stop-color:#FCEE1F"/>
<stop offset="1" style="stop-color:#F15B2A"/>
</linearGradient>
<path class="st1" d="M122.9,49.9c-0.2-1.9-0.5-4.1-1.1-6.5c-0.6-2.4-1.6-5-2.9-7.8c-1.4-2.7-3.1-5.6-5.4-8.3
c-0.9-1.1-1.9-2.1-2.9-3.2c1.6-6.3-1.9-11.8-1.9-11.8c-6.1-0.4-9.9,1.9-11.3,2.9c-0.2-0.1-0.5-0.2-0.7-0.3c-1-0.4-2.1-0.8-3.2-1.2
c-1.1-0.3-2.2-0.7-3.3-0.9c-1.1-0.3-2.3-0.5-3.5-0.7c-0.2,0-0.4-0.1-0.6-0.1C83.5,3.6,75.9,0,75.9,0c-8.7,5.6-10.4,13.1-10.4,13.1
s0,0.2-0.1,0.4c-0.5,0.1-0.9,0.3-1.4,0.4c-0.6,0.2-1.3,0.4-1.9,0.7c-0.6,0.3-1.3,0.5-1.9,0.8c-1.3,0.6-2.5,1.2-3.8,1.9
c-1.2,0.7-2.4,1.4-3.5,2.2c-0.2-0.1-0.3-0.2-0.3-0.2c-11.7-4.5-22.1,0.9-22.1,0.9c-0.9,12.5,4.7,20.3,5.8,21.7
c-0.3,0.8-0.5,1.5-0.8,2.3c-0.9,2.8-1.5,5.7-1.9,8.7c-0.1,0.4-0.1,0.9-0.2,1.3c-10.8,5.3-14,16.3-14,16.3c9,10.4,19.6,11,19.6,11
l0,0c1.3,2.4,2.9,4.7,4.6,6.8c0.7,0.9,1.5,1.7,2.3,2.6c-3.3,9.4,0.5,17.3,0.5,17.3c10.1,0.4,16.7-4.4,18.1-5.5c1,0.3,2,0.6,3,0.9
c3.1,0.8,6.3,1.3,9.4,1.4c0.8,0,1.6,0,2.4,0h0.4H80h0.5H81l0,0c4.7,6.8,13.1,7.7,13.1,7.7c5.9-6.3,6.3-12.4,6.3-13.8l0,0
c0,0,0,0,0-0.1s0-0.2,0-0.2l0,0c0-0.1,0-0.2,0-0.3c1.2-0.9,2.4-1.8,3.6-2.8c2.4-2.1,4.4-4.6,6.2-7.2c0.2-0.2,0.3-0.5,0.5-0.7
c6.7,0.4,11.4-4.2,11.4-4.2c-1.1-7-5.1-10.4-5.9-11l0,0c0,0,0,0-0.1-0.1l-0.1-0.1l0,0l-0.1-0.1c0-0.4,0.1-0.8,0.1-1.3
c0.1-0.8,0.1-1.5,0.1-2.3v-0.6v-0.3v-0.1c0-0.2,0-0.1,0-0.2v-0.5v-0.6c0-0.2,0-0.4,0-0.6s0-0.4-0.1-0.6l-0.1-0.6l-0.1-0.6
c-0.1-0.8-0.3-1.5-0.4-2.3c-0.7-3-1.9-5.9-3.4-8.4c-1.6-2.6-3.5-4.8-5.7-6.8c-2.2-1.9-4.6-3.5-7.2-4.6c-2.6-1.2-5.2-1.9-7.9-2.2
c-1.3-0.2-2.7-0.2-4-0.2h-0.5h-0.1h-0.2h-0.2h-0.5c-0.2,0-0.4,0-0.5,0c-0.7,0.1-1.4,0.2-2,0.3c-2.7,0.5-5.2,1.5-7.4,2.8
c-2.2,1.3-4.1,3-5.7,4.9s-2.8,3.9-3.6,6.1c-0.8,2.1-1.3,4.4-1.4,6.5c0,0.5,0,1.1,0,1.6c0,0.1,0,0.3,0,0.4v0.4c0,0.3,0,0.5,0.1,0.8
c0.1,1.1,0.3,2.1,0.6,3.1c0.6,2,1.5,3.8,2.7,5.4s2.5,2.8,4,3.8s3,1.7,4.6,2.2c1.6,0.5,3.1,0.7,4.5,0.6c0.2,0,0.4,0,0.5,0
c0.1,0,0.2,0,0.3,0s0.2,0,0.3,0c0.2,0,0.3,0,0.5,0h0.1h0.1c0.1,0,0.2,0,0.3,0c0.2,0,0.4-0.1,0.5-0.1c0.2,0,0.3-0.1,0.5-0.1
c0.3-0.1,0.7-0.2,1-0.3c0.6-0.2,1.2-0.5,1.8-0.7c0.6-0.3,1.1-0.6,1.5-0.9c0.1-0.1,0.3-0.2,0.4-0.3c0.5-0.4,0.6-1.1,0.2-1.6
c-0.4-0.4-1-0.5-1.5-0.3C88,74,87.9,74,87.7,74.1c-0.4,0.2-0.9,0.4-1.3,0.5c-0.5,0.1-1,0.3-1.5,0.4c-0.3,0-0.5,0.1-0.8,0.1
c-0.1,0-0.3,0-0.4,0c-0.1,0-0.3,0-0.4,0s-0.3,0-0.4,0c-0.2,0-0.3,0-0.5,0c0,0-0.1,0,0,0h-0.1h-0.1c-0.1,0-0.1,0-0.2,0
s-0.3,0-0.4-0.1c-1.1-0.2-2.3-0.5-3.4-1c-1.1-0.5-2.2-1.2-3.1-2.1c-1-0.9-1.8-1.9-2.5-3.1c-0.7-1.2-1.1-2.5-1.3-3.8
c-0.1-0.7-0.2-1.4-0.1-2.1c0-0.2,0-0.4,0-0.6c0,0.1,0,0,0,0v-0.1v-0.1c0-0.1,0-0.2,0-0.3c0-0.4,0.1-0.7,0.2-1.1c0.5-3,2-5.9,4.3-8.1
c0.6-0.6,1.2-1.1,1.9-1.5c0.7-0.5,1.4-0.9,2.1-1.2c0.7-0.3,1.5-0.6,2.3-0.8s1.6-0.4,2.4-0.4c0.4,0,0.8-0.1,1.2-0.1
c0.1,0,0.2,0,0.3,0h0.3h0.2c0.1,0,0,0,0,0h0.1h0.3c0.9,0.1,1.8,0.2,2.6,0.4c1.7,0.4,3.4,1,5,1.9c3.2,1.8,5.9,4.5,7.5,7.8
c0.8,1.6,1.4,3.4,1.7,5.3c0.1,0.5,0.1,0.9,0.2,1.4v0.3V66c0,0.1,0,0.2,0,0.3c0,0.1,0,0.2,0,0.3v0.3v0.3c0,0.2,0,0.6,0,0.8
c0,0.5-0.1,1-0.1,1.5c-0.1,0.5-0.1,1-0.2,1.5s-0.2,1-0.3,1.5c-0.2,1-0.6,1.9-0.9,2.9c-0.7,1.9-1.7,3.7-2.9,5.3
c-2.4,3.3-5.7,6-9.4,7.7c-1.9,0.8-3.8,1.5-5.8,1.8c-1,0.2-2,0.3-3,0.3H81h-0.2h-0.3H80h-0.3c0.1,0,0,0,0,0h-0.1
c-0.5,0-1.1,0-1.6-0.1c-2.2-0.2-4.3-0.6-6.4-1.2c-2.1-0.6-4.1-1.4-6-2.4c-3.8-2-7.2-4.9-9.9-8.2c-1.3-1.7-2.5-3.5-3.5-5.4
s-1.7-3.9-2.3-5.9c-0.6-2-0.9-4.1-1-6.2v-0.4v-0.1v-0.1v-0.2V60v-0.1v-0.1v-0.2v-0.5V59l0,0v-0.2c0-0.3,0-0.5,0-0.8
c0-1,0.1-2.1,0.3-3.2c0.1-1.1,0.3-2.1,0.5-3.2c0.2-1.1,0.5-2.1,0.8-3.2c0.6-2.1,1.3-4.1,2.2-6c1.8-3.8,4.1-7.2,6.8-9.9
c0.7-0.7,1.4-1.3,2.2-1.9c0.3-0.3,1-0.9,1.8-1.4c0.8-0.5,1.6-1,2.5-1.4c0.4-0.2,0.8-0.4,1.3-0.6c0.2-0.1,0.4-0.2,0.7-0.3
c0.2-0.1,0.4-0.2,0.7-0.3c0.9-0.4,1.8-0.7,2.7-1c0.2-0.1,0.5-0.1,0.7-0.2c0.2-0.1,0.5-0.1,0.7-0.2c0.5-0.1,0.9-0.2,1.4-0.4
c0.2-0.1,0.5-0.1,0.7-0.2c0.2,0,0.5-0.1,0.7-0.1c0.2,0,0.5-0.1,0.7-0.1l0.4-0.1l0.4-0.1c0.2,0,0.5-0.1,0.7-0.1
c0.3,0,0.5-0.1,0.8-0.1c0.2,0,0.6-0.1,0.8-0.1c0.2,0,0.3,0,0.5-0.1h0.3h0.2h0.2c0.3,0,0.5,0,0.8-0.1h0.4c0,0,0.1,0,0,0h0.1h0.2
c0.2,0,0.5,0,0.7,0c0.9,0,1.8,0,2.7,0c1.8,0.1,3.6,0.3,5.3,0.6c3.4,0.6,6.7,1.7,9.6,3.2c2.9,1.4,5.6,3.2,7.8,5.1
c0.1,0.1,0.3,0.2,0.4,0.4c0.1,0.1,0.3,0.2,0.4,0.4c0.3,0.2,0.5,0.5,0.8,0.7c0.3,0.2,0.5,0.5,0.8,0.7c0.2,0.3,0.5,0.5,0.7,0.8
c1,1,1.9,2.1,2.7,3.1c1.6,2.1,2.9,4.2,3.9,6.2c0.1,0.1,0.1,0.2,0.2,0.4c0.1,0.1,0.1,0.2,0.2,0.4s0.2,0.5,0.4,0.7
c0.1,0.2,0.2,0.5,0.3,0.7c0.1,0.2,0.2,0.5,0.3,0.7c0.4,0.9,0.7,1.8,1,2.7c0.5,1.4,0.8,2.6,1.1,3.6c0.1,0.4,0.5,0.7,0.9,0.7
c0.5,0,0.8-0.4,0.8-0.9C123,52.7,123,51.4,122.9,49.9z"/>
</svg>

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><ellipse cx="49.5" cy="258.3" rx="49.5" ry="49.9" style="fill-rule:evenodd;clip-rule:evenodd;fill:#f8b5cb"/><path d="M135.9 220.2c7.8 0 14.2 6.3 14.2 14s-6.4 14-14.2 14-14.2-6.3-14.2-14 6.4-14 14.2-14m0 49c7.8 0 14.2 6.3 14.2 14s-6.4 14-14.2 14-14.2-6.3-14.2-14 6.4-14 14.2-14m64 0c7.8 0 14.2 6.3 14.2 14s-6.4 14-14.2 14-14.2-6.3-14.2-14 6.4-14 14.2-14m.2-49c7.8 0 14.2 6.3 14.2 14s-6.4 14-14.2 14-14.2-6.3-14.2-14 6.4-14 14.2-14" style="fill-rule:evenodd;clip-rule:evenodd;fill:#a2a2a2"/><path d="M325 208.8c27.4 0 49.6 22.4 49.6 50s-22.2 50-49.6 50-49.6-22.4-49.6-50 22.2-50 49.6-50m106.6 0c27.4 0 49.6 22.4 49.6 50s-22.2 50-49.6 50-49.6-22.4-49.6-50 22.2-50 49.6-50" style="fill-rule:evenodd;clip-rule:evenodd;fill:#8d8d8d"/><path d="M273.3 173.5h-28.8v165h28.8v-11.9h-17v-141h17zm209.9 0H512v165h-28.8v-11.9h17v-141h-17z" style="fill-rule:evenodd;clip-rule:evenodd;fill:#303030"/></svg>

After

Width:  |  Height:  |  Size: 974 B

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><path d="M244.2 502.3c-25.1-1-49.2-5.4-72.6-13.3-77.4-26.1-138-87.1-161.3-162.4C.2 294.1-2.5 258 2.3 222.3c4.7-34.9 17.3-68 37.3-98.2 15.3-23.2 37-46.1 60-63.3 46.9-35.1 109.2-54 168.2-51 32.9 1.7 63.4 8.6 92.9 21.1 10.4 4.4 25.4 12.3 35.2 18.5 18 11.3 28.4 19.7 43.8 35 16.8 16.8 28.1 30.8 38.6 48.1 9.2 15.1 17.9 34.5 23.2 51.3 2 6.5 5.6 20.9 7.2 28.8 3 15.1 3.4 20 3.4 42.3 0 23.5-.6 31-3.7 46.7-11.8 59.6-45.2 112-95.1 149.4-29 21.7-63.5 37.5-99.8 45.5-21.3 4.8-45.1 6.7-69.3 5.8m-44.6-100.1c0-.7-.1-2.6-.2-4.3l-.2-3.1-6-.3c-5.1-.3-6.1-.4-6.8-1-2.6-1.9-1.9-7.7 2.9-23.4 1.1-3.7 4.2-14.4 7-23.8 2.7-9.5 6.6-22.7 8.6-29.3 2-6.7 5.3-18.1 7.4-25.5 2.1-7.3 4.6-15.8 5.5-18.8s4.1-14 7.2-24.5c6.3-21.6 10.4-35.2 11.4-37.9.7-1.8.7-1.8 1.3-1.2.3.3 4.9 9.4 10.1 20.1 5.3 10.7 16.6 33.8 25.3 51.2 21.8 44.1 48.1 97.3 55 111.3l5.8 11.8 14.4-.1c7.9-.1 14.8-.2 15.2-.4.7-.3.7-.4-1.7-5.5-1.4-2.9-10.3-21.1-20-40.5-62.1-125-78-157.4-86.5-176-6-13.1-8.8-18.8-9.8-20-1.1-1.2-2.1-1.4-3-.3-1.5 1.7-5.2 12.8-11.9 35.9-2.6 9-8.3 28.5-12.6 43.3-8.4 28.7-10.8 36.9-18.2 62.1-2.6 8.8-6.1 20.8-7.8 26.6s-5.1 17.5-7.6 26.1c-5.5 18.9-7.8 26.5-9.4 30.8-2.7 7.3-3.3 8-6.3 8.6-1.1.2-3.1.4-4.3.4-2.8 0-4.5.5-5.2 1.4-.5.8-.7 6.2-.2 7 .3.4 3.1.5 29.6.7l10.9.1zm46.7-261.1c5.5-1.2 10.7-6.3 12-11.7.5-2 .4-6.3-.1-8.2-1.1-4-4.2-8-7.7-9.9-4.8-2.6-12-2.6-16.9 0-7.6 4.1-10.4 14.1-6.1 22.1 3.5 6.4 10.7 9.4 18.8 7.7" style="fill:#f0f0f0"/><path d="M2712.8 5196.2c-157.5-82.6-156.2-323.9 3.8-405.2 109.2-55.9 249-20.3 313.7 78.8 73.7 110.5 33 268-85.1 327.7-64.7 33-167.6 33-232.4-1.3z" style="fill:#00b6f0;stroke:#00b6f0;stroke-width:.297;stroke-miterlimit:10" transform="matrix(.0699 0 0 -.0699 44.236 474.48)"/><path d="M2833.5 4483.6c-15.2-20.3-80-210.9-129.6-384.9-38.1-132.1-128.3-444.6-209.6-717.7-25.4-87.6-73.7-252.8-108-368.4-33-115.6-81.3-280.7-108-368.4-25.4-87.6-73.7-252.8-108-368.4-33-115.6-81.3-280.7-108-368.4-25.4-87.6-72.4-247.7-102.9-355.7-74.9-262.9-118.1-379.8-146.1-393.8-12.7-7.6-44.5-12.7-71.1-12.7-92.7 0-106.7-10.2-102.9-68.6l3.8-52.1 289.6-3.8 289.6-2.5-3.8 59.7-3.8 61-92.7 3.8c-83.8 3.8-94 6.4-106.7 34.3-16.5 35.6 0 132.1 47 285.8 16.5 52.1 59.7 198.2 95.3 323.9 35.6 125.8 83.8 292.2 108 368.4 22.9 77.5 71.1 242.6 108 368.4 35.6 125.8 83.8 292.2 108 368.4 22.9 77.5 71.1 242.6 108 368.4 108 377.3 156.2 532.2 166.4 544.9 6.4 6.4 21.6-14 35.6-44.5 12.7-30.5 243.9-499.2 511.9-1040.3s567.8-1145.7 664.3-1343.9l176.6-358.2h213.4c116.9 0 213.4 5.1 213.4 10.2s-95.3 200.7-210.9 434.4C3613.4 2965.6 3129.4 3950 3048.2 4130.4c-36.8 80-87.6 191.8-113.1 247.7-55.9 120.8-73.7 139.8-101.6 105.5" style="fill:#575757" transform="matrix(.0699 0 0 -.0699 44.236 474.48)"/></svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><path d="M471.8 319.8c-17.3 0-32 10.9-37.7 26.2H189.7c-4.1-11-12.8-19.6-23.7-23.7V77.9c15.3-5.7 26.2-20.4 26.2-37.7C192.2 18 174.2 0 152 0s-40.2 18-40.2 40.2c0 17.3 10.9 32 26.2 37.7v244.4c-15.3 5.7-26.2 20.4-26.2 37.7 0 6 1.3 11.7 3.7 16.8L57 435.3c-5.1-2.4-10.8-3.7-16.8-3.7-22.2 0-40.2 18-40.2 40.2S18 512 40.2 512s40.2-18 40.2-40.2c0-6-1.3-11.7-3.7-16.8l58.5-58.5c5.1 2.4 10.8 3.7 16.8 3.7 17.3 0 32-10.9 37.7-26.2h244.4c5.7 15.3 20.4 26.2 37.7 26.2 22.2 0 40.2-18 40.2-40.2s-18-40.2-40.2-40.2" style="fill:#001423"/><path d="M512 40.2c0 22.2-18 40.2-40.2 40.2-6 0-11.7-1.3-16.8-3.7l-58.5 58.5c2.4 5.1 3.7 10.8 3.7 16.8 0 17.3-10.9 32-26.2 37.7v244.4c15.3 5.7 26.2 20.4 26.2 37.7 0 22.2-18 40.2-40.2 40.2s-40.2-18-40.2-40.2c0-17.3 10.9-32 26.2-37.7V189.7c-11-4.1-19.6-12.8-23.7-23.7H77.9c-5.7 15.3-20.4 26.2-37.7 26.2C18 192.2 0 174.2 0 152s18-40.2 40.2-40.2c17.3 0 32 10.9 37.7 26.2h244.4c5.7-15.3 20.4-26.2 37.7-26.2 6 0 11.7 1.3 16.8 3.7L435.3 57c-2.4-5.1-3.7-10.8-3.7-16.8 0-22.2 18-40.2 40.2-40.2S512 18 512 40.2" style="fill:#00857d"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><linearGradient id="jellyfin_svg__a" x1="97.487" x2="522.047" y1="483.902" y2="729.018" gradientTransform="translate(0 -278)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#aa5cc3"/><stop offset="1" style="stop-color:#00a4dc"/></linearGradient><path d="M256 196.2c-22.4 0-94.8 131.3-83.8 153.4s156.8 21.9 167.7 0-61.3-153.4-83.9-153.4" style="fill:url(#jellyfin_svg__a)"/><linearGradient id="jellyfin_svg__b" x1="94.186" x2="518.747" y1="489.619" y2="734.735" gradientTransform="translate(0 -278)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#aa5cc3"/><stop offset="1" style="stop-color:#00a4dc"/></linearGradient><path d="M256 0C188.3 0-29.8 395.4 3.4 462.2s472.3 66 505.2 0S323.8 0 256 0m165.6 404.3c-21.6 43.2-309.3 43.8-331.1 0S211.7 101.4 256 101.4 443.2 361 421.6 404.3" style="fill:url(#jellyfin_svg__b)"/></svg>

After

Width:  |  Height:  |  Size: 945 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 35 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 240 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><circle cx="256" cy="256" r="256" style="fill-rule:evenodd;clip-rule:evenodd;fill:#5856e0"/><path d="m277.2 432.7-22.2-22 160.2-161.3.1-.1c.1-.1 11.5-11.7 16.3-29.1 6-22-1.3-43.8-21.8-64.6-15.6-15.9-31.9-24-48.3-24-25.6 0-44.9 19.3-45.1 19.5l-.1.1-160.1 161.3-22.2-22 160.1-161.3c2.3-2.4 29-28.7 67-28.9h.4c25.2 0 49 11.2 70.6 33.3 36.5 37.2 36 72.9 29.1 96.3-7.1 24.1-21.9 39.4-24 41.5zm-124.3-19.9c-25.3 0-49.1-11.3-70.8-33.6-36.3-37.4-35.7-73.1-28.7-96.4 7.2-24.1 22.1-39.3 24.1-41.4L238.3 80.7l22.1 22.1L99.5 263.5l-.1.1c-.1.1-11.5 11.7-16.4 29-6.1 22 1.1 43.8 21.5 64.7 15.5 15.9 31.8 24.1 48.3 24.1h.2c25.5 0 44.8-19.2 45-19.4l.1-.1 160.8-160.8 22.1 22.1-160.8 160.9c-2.3 2.4-29.1 28.6-67.1 28.7z" style="fill:#fff"/></svg>

After

Width:  |  Height:  |  Size: 813 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><linearGradient id="mastodon_svg__a" x1="253.986" x2="253.986" y1="279" y2="791.028" gradientTransform="translate(2 -279)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#6364ff"/><stop offset="1" style="stop-color:#563acc"/></linearGradient><path d="M494.3 113.4C486.9 58.3 439 15 382.1 6.6 372.5 5.2 336.2 0 252 0h-.6c-84.2 0-102.2 5.2-111.8 6.6-55.3 8.2-105.7 47.1-118 102.8-5.9 27.4-6.5 57.8-5.4 85.7 1.6 40 1.9 79.9 5.5 119.7 2.5 26.4 6.9 52.7 13.1 78.5 11.6 47.7 58.7 87.4 104.9 103.6 49.4 16.9 102.6 19.7 153.5 8.1 5.6-1.3 11.1-2.8 16.6-4.5 12.4-3.9 26.9-8.3 37.5-16.1.1-.1.3-.2.4-.4s.1-.3.1-.5v-38.6c0-.2 0-.3-.1-.5s-.2-.3-.3-.4-.3-.2-.5-.2h-.5c-32.6 7.8-66.1 11.7-99.6 11.6-57.7 0-73.2-27.4-77.7-38.8-3.6-9.9-5.8-20.1-6.7-30.6 0-.2 0-.4.1-.5.1-.2.2-.3.3-.4s.3-.2.5-.2h.5c32.1 7.7 65 11.6 98 11.6 7.9 0 15.8 0 23.8-.2 33.2-.9 68.2-2.6 100.8-9 .8-.2 1.6-.3 2.3-.5 51.5-9.9 100.5-40.9 105.5-119.5.2-3.1.7-32.4.7-35.6-.1-11 3.4-77.5-.6-118.3" style="fill:url(#mastodon_svg__a)"/><path d="M412.7 175.2v136.7h-54.2V179.2c0-27.9-11.6-42.2-35.3-42.2-26 0-39.1 16.8-39.1 50.1v72.6h-53.8v-72.6c0-33.3-13.1-50.1-39.1-50.1-23.5 0-35.3 14.2-35.3 42.2v132.6h-54.1V175.2c0-27.9 7.1-50.1 21.4-66.6 14.7-16.4 34-24.8 58-24.8 27.7 0 48.7 10.7 62.6 32l13.5 22.6 13.5-22.6c14-21.3 34.9-32 62.6-32 23.9 0 43.2 8.4 58 24.8q21.3 24.6 21.3 66.6" style="fill:#fff"/></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><path d="M512 80v352c0 44.2-35.8 80-80 80H80c-44.2 0-80-35.8-80-80V80C0 35.8 35.8 0 80 0h352c44.2 0 80 35.8 80 80" style="fill-rule:evenodd;clip-rule:evenodd;fill:#0082c9"/><path d="M256 167.2c-40.3 0-74.5 27.2-85.3 64.2-9.3-19.4-29-33-51.8-33-31.6-.1-57.6 25.9-57.6 57.6s26 57.6 57.6 57.6c22.8 0 42.5-13.6 51.8-33 10.8 36.9 45 64.2 85.3 64.2s74.5-27.2 85.3-64.2c9.3 19.4 29 33 51.8 33 31.6 0 57.6-26 57.6-57.6s-25.8-57.7-57.5-57.7c-22.8 0-42.5 13.6-51.8 33-10.9-36.9-45.1-64.1-85.4-64.1m0 34.2c30.3 0 54.5 24.2 54.5 54.5s-24.2 54.5-54.5 54.5-54.5-24.2-54.5-54.5 24.2-54.5 54.5-54.5m-137 31.2c13.1 0 23.3 10.2 23.3 23.3s-10.2 23.3-23.3 23.3S95.5 269 95.5 256s10.3-23.4 23.5-23.4m274.1 0c13.1 0 23.3 10.2 23.3 23.3s-10.2 23.3-23.3 23.3-23.3-10.2-23.3-23.2 10.2-23.4 23.3-23.4" style="fill:#fff"/></svg>

After

Width:  |  Height:  |  Size: 884 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" viewBox="0 0 512 512"><circle cx="256" cy="256" r="256" style="fill:#fff"/><defs><circle id="ollama_svg__a" cx="256" cy="256" r="256"/></defs><clipPath id="ollama_svg__b"><use xlink:href="#ollama_svg__a" style="overflow:visible"/></clipPath><g style="clip-path:url(#ollama_svg__b)"><path d="M157.3 35.9c-4.3.7-9.5 3-13.1 5.7-11 8.4-19.6 26.2-23.2 48.4-1.4 8.4-2.3 20-2.3 28.9 0 10.5 1.2 23.9 3 33.1.4 2.1.6 3.9.4 4-.1.1-1.8 1.5-3.6 2.9-6.2 5-13.4 12.6-18.3 19.6-9.4 13.4-15.5 28.6-18.1 45-1 6.5-1.3 19.6-.5 26.1 1.8 15 6.3 27.7 14 39.3l2.5 3.7-.7 1.2c-5.2 8.7-9.6 21.3-11.6 33.3-1.6 9.6-1.8 12.1-1.8 24.9 0 12.9.2 15.5 1.7 24.4 1.8 10.7 5.5 22 9.7 29.5 1.4 2.5 4.7 7.6 5.1 7.8.1.1-.3 1.3-.9 2.7-4.8 10.5-8.9 24.4-10.6 36.1-1.2 8-1.4 10.6-1.4 19.1 0 10.8.6 16 2.9 24.6l.3 1.3h28.4l-.9-1.8c-5.7-10.6-6.3-30.3-1.3-50 2.3-9.1 4.8-15.8 9.6-24.9l2.9-5.6v-3.4c0-3.2-.1-3.5-1.1-5.6-.8-1.6-1.9-3-3.7-4.8-3.2-3.1-5.5-6.4-7.4-10.5-8.2-17.7-9.8-44-4-66.5 2.4-9.4 6.3-17.7 10.5-22.2 2.8-3.1 4.3-6.6 4.3-10.2 0-3.7-1.3-6.8-4.3-10.1-8.6-9.2-13.8-20.3-15.7-33.3-2.7-18.5 2.2-38.6 13.3-54.6 10.8-15.7 26.1-25.7 43.1-28.4 3.8-.6 10.9-.5 14.9.2 4.3.8 7.1.5 9.9-.8 3.5-1.6 5.2-3.6 7.2-8.3 1.8-4.1 3.2-6.4 6.9-11.1 4.5-5.6 8.9-9.4 15.8-14 8-5.2 17-9 26-10.8 3.3-.7 4.8-.8 10.9-.8s7.7.1 10.9.8c13.2 2.7 26.4 9.5 36.9 19.2 2.3 2.1 7.7 8.8 9.4 11.6.7 1.1 1.8 3.4 2.6 5.1 2 4.6 3.7 6.7 7.2 8.3 2.7 1.3 5.5 1.6 9.7.9 6.6-1.1 11.7-1 18.1.3 22 4.4 41.2 22.6 49.7 46.9 7.4 21.3 5.3 43.7-5.7 60.7-1.9 2.9-3.7 5.2-6.4 8.1-5.8 6.2-5.8 13.9 0 20.3 9.5 10.4 15.4 35.9 13.6 58.5-1.2 14.9-5 28.2-10.3 35.7-.9 1.3-2.9 3.6-4.3 5-1.9 1.9-3 3.2-3.7 4.8-1 2.1-1.1 2.5-1.1 5.6v3.4l2.9 5.6c4.8 9.2 7.3 15.9 9.6 24.9 4.9 19.4 4.4 38.7-1.1 49.7-.5.9-.9 1.8-.9 1.9s6.3.2 14.1.2h14.1l.4-1.4c.2-.8.5-1.9.7-2.6.4-1.5 1.1-5.8 1.7-9.9.6-4.2.6-19.6 0-24.2-2.1-16.9-5.7-30.2-11.5-42.9-.6-1.4-1-2.7-.9-2.7.2-.1 1.1-1.4 2.1-2.9 7.2-10.9 11.7-24.7 13.9-42.9.6-5 .6-26.5 0-31.4-1.6-12.4-3.5-20.8-6.7-29.4-1.3-3.5-4.8-11-6.3-13.5l-.7-1.2 2.5-3.7c7.7-11.6 12.2-24.3 14-39.3.8-6.5.5-19.6-.5-26.1-2.6-16.5-8.7-31.6-18.1-45-4.9-7-12-14.7-18.3-19.6-1.8-1.5-3.5-2.8-3.6-2.9-.2-.1 0-2 .4-4 4-20.9 3.9-47-.3-67.4-3.6-17.8-10.3-31.9-18.8-40.1-6.8-6.5-13.8-9.3-22.2-8.8-19.2 1.1-34.6 23.2-40.7 58-1 5.6-1.9 12.2-1.9 14 0 .7-.1 1.3-.3 1.3s-1.5-.7-2.9-1.5C288.5 98.8 272 94.1 256 94.1s-32.5 4.7-47.3 13.4c-1.4.8-2.7 1.5-2.9 1.5s-.3-.6-.3-1.3c0-1.9-.9-8.6-1.9-14-5.5-31.2-18.2-51.9-35.1-57.1-2.2-.6-8.8-1.1-11.2-.7m5.6 27c4.8 3.8 10.1 14.6 13.1 26.7.6 2.2 1.2 4.7 1.3 5.6s.5 2.9.8 4.5c1.3 7 1.9 14.6 2 23.9v9.1l-2.3 3.4-2.3 3.4h-5.3c-6.2 0-12.4.8-18.4 2.4-2.1.5-4.2 1.1-4.6 1.2-.6.1-.7-.1-1.1-2.8-2-14.8-1.9-31.1.3-44.7 2.4-15.2 8-28.9 13.4-32.9 1.4-1 1.6-1 3.1.2m189.2-.2c3.3 2.4 6.9 8.9 9.6 17.1 5.4 16.5 6.9 39 4.1 60.5-.4 2.7-.5 2.9-1.1 2.8-.4-.1-2.5-.6-4.6-1.2-5.9-1.6-12.1-2.4-18.4-2.4h-5.3l-2.3-3.4-2.3-3.4v-9.1c.1-12.9 1.3-22.9 4.1-34.1 3-12 8.4-22.8 13.1-26.6 1.6-1.2 1.8-1.2 3.1-.2"/><path d="M250.9 229.6c-7.2.7-9.2 1-12.6 1.7-5.6 1.2-13.1 3.7-18.3 6.3-18.1 8.9-30.6 23.6-34.4 40.7-.8 3.4-.9 4.5-.9 10.2 0 5.6.1 6.9.8 10.1 5.1 22.3 25.6 38.8 52.3 41.8 5.8.6 30.7.6 36.5 0 21.4-2.4 39.7-14 48-30.3 2.2-4.3 3.3-7.2 4.2-11.6.7-3.2.8-4.4.8-10.1s-.1-6.8-.9-10.2c-5.5-24.8-29.6-44.4-59.2-48.1-3.7-.3-13.8-.7-16.3-.5m12.4 18.1c9.9 1.1 19.8 4.6 27.7 9.9 4.3 2.9 10.3 8.8 12.9 12.7 3.2 4.8 5 9.8 5.8 15.8.4 2.8.2 4.8-.8 9.3-1.6 6.6-6.4 13.6-12.9 18.4-3.1 2.2-9.4 5.4-13.3 6.7-7.4 2.4-12.2 2.8-29.4 2.7-11.2-.1-13.2-.2-16.4-.8-11-2.1-19.7-6.4-26-13.1-5.1-5.4-7.4-10.3-8.7-18.2-.6-3.7.5-9.8 2.7-14.9 2.6-6.3 9.4-14.1 16.1-18.5 7.8-5.2 18-8.9 27.4-9.9 3.6-.5 11.2-.5 14.9-.1"/><path d="M243.3 271.9c-2.5 1.4-4.3 4.8-3.7 7.4.6 2.8 3 5.5 6.8 7.8 2 1.2 2.2 1.4 2.3 2.6.1.7-.2 2.8-.6 4.7-.4 1.8-.7 3.7-.7 4.3 0 1.4 1.4 3.7 2.8 4.9 1.2 1 1.5 1 4.9 1.1 3.2.1 3.8 0 5.1-.6 3.3-1.6 4.1-4.5 2.9-10.1-1-4.7-.8-5.4 1.7-6.8 2.6-1.5 5.4-4.2 6.2-6 1.6-3.5.1-7.4-3.4-9.3-.9-.4-1.9-.6-3.5-.6-2.4 0-4 .6-6.8 2.4l-1.6 1-1-.6c-4.2-2.5-5-2.8-7.5-2.8-2 0-3 .1-3.9.6m-80.5-38.5c-5.9 1.9-10.3 6.2-12.5 12.3-1.1 2.9-1.6 7.5-1.2 10 1.1 5.9 6 11.3 11.5 12.8 7 1.8 12.2.6 16.8-3.9 2.7-2.6 4.1-4.9 5.6-8.6 1.1-2.6 1.1-3.1 1.1-6.8v-4l-1.4-2.9c-2.2-4.5-6.2-7.9-10.9-9.1-2.5-.6-6.7-.6-9 .2m177.2-.1c-4.5 1.2-8.6 4.6-10.7 9.1l-1.4 2.9v4c0 3.7.1 4.2 1.1 6.8 1.5 3.7 2.9 6 5.6 8.6 4.6 4.6 9.8 5.8 16.8 3.9 4-1.1 8-4.4 10-8.4 1.7-3.4 2.1-5.8 1.5-9.6-1.2-8.7-6.3-15.1-13.9-17.3-2.3-.7-6.6-.7-9 0"/></g></svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><path d="M224 486.5 13.5 389.2c-17.9-8.5-17.9-21.6 0-29.4l73.3-34 136.5 63.3c17.9 8.5 46.8 8.5 64 0l136.5-63.3 73.3 34c17.9 8.5 17.9 21.6 0 29.4l-210.6 97.3c-16.5 7.7-45.3 7.7-62.5 0" style="fill-rule:evenodd;clip-rule:evenodd;fill:#ff6f3d"/><path d="M224 366.8 13.5 269.4c-17.9-8.5-17.9-21.6 0-29.4l71.7-33.2L224 271c17.9 8.5 46.8 8.5 64 0l138.8-64.1 71.8 33.2c17.9 8.5 17.9 21.6 0 29.4L288 366.8c-18 8.5-46.8 8.5-64 0" style="fill-rule:evenodd;clip-rule:evenodd;fill:#95c038"/><path d="M224 250.1 13.5 152.8c-17.9-8.5-17.9-21.6 0-29.4L224 26.1c17.9-8.5 46.8-8.5 64 0l210.6 97.3c17.9 8.5 17.9 21.6 0 29.4L288 250.1c-18 7.7-46.8 7.7-64 0" style="fill-rule:evenodd;clip-rule:evenodd;fill:#5dc0e8"/></svg>

After

Width:  |  Height:  |  Size: 787 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><path d="M231.4 117.8c-37.9 0-68.6 30.7-68.6 68.6 0 15.4 5.1 29.7 14.3 42 19.5-22.5 47.1-35.8 78.8-35.8 15.4 0 29.7 3.1 43 9.2 1-5.1 2-10.2 2-15.4.2-37.9-30.6-68.6-69.5-68.6m-89.1 31.7c-19.5 0-35.8 16.4-35.8 35.8 0 6.1 2 12.3 4.1 17.4 12.3-7.2 25.6-10.2 41-10.2h4.1v-6.1c0-11.3 2-21.5 6.1-30.7-6.2-4.1-12.3-6.2-19.5-6.2m169 24.6h-4.1c1 4.1 1 8.2 1 12.3 0 6.1-1 12.3-2 18.4 17.4 9.2 31.7 23.6 41 42 10.2-5.1 20.5-8.2 32.8-9.2-3.2-35.9-31.8-63.5-68.7-63.5M256 199.7c-53.2 0-96.3 43-96.3 96.3s43 96.3 96.3 96.3 96.3-43 96.3-96.3-43.1-96.3-96.3-96.3m-104.4 1c-41 0-74.8 33.8-74.8 74.8 0 24.6 11.3 46.1 29.7 59.4 7.2-14.3 22.5-24.6 39.9-24.6 2 0 4.1 0 6.1 1-1-5.1-1-9.2-1-14.3 0-23.6 7.2-45.1 20.5-62.5-8.2-9.2-13.3-21.5-15.4-33.8zm234.4 44c-12.3 0-24.6 3.1-34.8 8.2 6.1 13.3 9.2 27.6 9.2 43 0 28.7-11.3 54.3-29.7 73.7 13.3 15.4 33.8 24.6 55.3 24.6 41 0 74.8-33.8 74.8-74.8 0-40.9-33.8-74.7-74.8-74.7M68.6 255C30.7 255 0 285.7 0 323.6s30.7 68.6 68.6 68.6c14.3 0 27.6-4.1 38.9-12.3-4.1-7.2-7.2-15.4-7.2-24.6 0-5.1 1-9.2 2-13.3-20.5-15.4-34.8-39.9-34.8-66.6 0-7.2 1-13.3 3.1-20.5.1.1-1 .1-2 .1m405.5 59.4c-2 0-4.1 0-6.1 1v5.1c0 21.5-8.2 42-22.5 56.3 7.2 8.2 17.4 13.3 28.7 13.3 20.5 0 37.9-16.4 37.9-37.9s-17.5-37.8-38-37.8m-327.7 3c-20.5 0-37.9 16.4-37.9 37.9s16.4 37.9 37.9 37.9c16.4 0 29.7-10.2 34.8-23.6-13.3-13.3-23.6-30.7-27.6-50.2-2-.9-5.1-2-7.2-2" style="fill:#0b1e41"/></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><linearGradient id="pi-hole_svg__a" x1="1124.653" x2="1839.97" y1="-669.315" y2="-669.315" gradientTransform="matrix(.3694 0 0 -.3694 -322.747 -168.195)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#12b212"/><stop offset="1" style="stop-color:#0f0"/></linearGradient><path d="M226.1 157.3C162.1 150.5 97.7 102.2 92.7 0 191.8 0 244.9 58.7 250 151.8c18.8-111.6 106.7-98.5 106.7-98.5 4.2 63.2-47.8 101.6-106.7 104.8-16.5-35-115.7-120.5-115.7-120.5-.1-.1-.3-.1-.4 0q-.15.15 0 .3s95.7 83.4 92.2 119.4" style="fill:url(#pi-hole_svg__a)"/><path d="M256 512c-6.2-.4-63.9-2.6-67.4-67.4-2.8-39.4 28.3-68.5 28.3-106.7-7.1-95.4-134.9-83.6-134.9 0-.1 20.9 8.2 40.9 23 55.7l95.2 95.3c14.8 14.8 34.8 23 55.8 23.1m0-348.1c6.2.4 63.9 2.6 67.4 67.4 2.8 39.4-28.3 68.5-28.3 106.7 7.1 95.4 134.8 83.6 134.8 0 .1-20.9-8.2-40.9-23-55.7L311.7 187c-14.8-14.8-34.8-23-55.7-23" style="fill:#91180c"/><path d="M430 337.9c-.4 6.2-2.6 63.9-67.4 67.4-39.4 2.8-68.5-28.3-106.7-28.3-95.4 7.1-83.6 134.8 0 134.8 20.9.1 40.9-8.2 55.7-23l95.3-95.2c14.8-14.8 23-34.8 23.1-55.7m-347.7 0c.4-6.2 2.6-63.9 67.4-67.4 39.4-2.8 68.5 28.3 106.7 28.3 95.4-7.2 83.6-134.8 0-134.8-20.9-.1-40.9 8.2-55.7 23l-95.3 95.3c-14.8 14.8-23 34.8-23 55.7" style="fill:#f42e1c"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><path d="M412 96.8 282.7 22V0h-16v21.8l-.2-.3-130.2 75.3H73.1v16h114.2v77.5h41.4v-77.5h38V335c.6 0 11.6-.2 16 1.9V112.8h11.4v226.3c6.2 3.1 11.7 6.6 16 11.5V112.8h128.8v-16zm-191.1 51.9h-25.8v-35.9h25.8zm-52.6-51.9 98.4-56.9v56.9zm114.4-56.3L380 96.8h-97.3zM82.6 304.7c0 26.2 12.9 49.2 32.4 63.7 5.1-1.4 10.2-2.2 15.4-2.4 2.2 0 3.5.2 5.7.4 6-25.4 29.5-42.4 56.8-42.4 15.4 0 30.7 4.3 41 14.3 4.8-10.2 6.4-21.5 6.4-33.6 0-13.9-3.5-27.6-10.5-39.5H93.1c-6.8 11.9-10.5 25.6-10.5 39.5m11.5-87.4h41.4v41.6H94.1zm46.7-46.3h41.4v41.6h-41.4zm-46.7 0h41.4v41.6H94.1zm46.7 46.3h41.4v41.6h-41.4zm46.5 0h41.4v41.6h-41.4zm135.6 179.4c0-30.1-24.4-54.5-54.5-54.5-11.5 0-22 3.5-30.8 9.6-10.2-11.8-25-19.2-41.6-19.2-25.8 0-47.4 18-53.1 42-1.9-.4-3.9-.4-5.9-.1-30.3 0-54.7 24.4-54.7 54.5s24.6 54.5 54.7 54.5c3.9 0 7.6-.4 11.3-1.2 9.2 17.6 27.5 29.7 48.6 29.7 18.3 0 34.5-9.2 44.5-23.1 9.4 7.8 21.5 12.5 34.8 12.5 30.1 0 54.5-24.4 54.5-54.5 0-12.1-4.1-23.4-10.7-32.4 1.9-5.7 2.9-11.5 2.9-17.8" style="fill-rule:evenodd;clip-rule:evenodd;fill:#13bef9"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><path d="M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256 256-114.6 256-256S397.4 0 256 0m0 479.1c-40.2 0-72.8-26.9-72.8-60h145.7c-.1 33.1-32.7 60-72.9 60m120.3-79.9H135.7v-43.6h240.6zm-.9-66h-239c-.8-.9-1.6-1.8-2.4-2.8-24.6-29.9-30.4-45.5-36.1-61.4-.1-.5 29.9 6.1 51.1 10.9 0 0 10.9 2.5 26.9 5.4-15.3-18-24.5-40.9-24.5-64.2 0-51.3 39.4-96.2 25.2-132.4 13.8 1.1 28.6 29.2 29.6 73 14.7-20.3 20.8-57.4 20.8-80.1 0-23.5 15.5-50.9 31-51.8-13.8 22.8 3.6 42.3 19.1 90.8 5.8 18.2 5.1 48.8 9.5 68.3 1.5-40.4 8.4-99.2 34-119.6-11.3 25.6 1.7 57.6 10.5 73 14.3 24.8 23 43.7 23 79.3 0 23.9-8.8 46.3-23.7 63.9 16.9-3.2 28.6-6 28.6-6l54.9-10.7c.2 0-7.8 32.8-38.5 64.4" style="fill:#e6522c"/></svg>

After

Width:  |  Height:  |  Size: 765 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><path d="m295.9 252.1-24.7-13c17.7-33.6 11.7-74.3-15.1-101.2s-67.5-33.4-101.3-15.9l-12.7-25c44.7-23 98.5-14.5 133.9 21.1 35.3 35.7 43.4 89.5 19.9 134M512 432.6 366.2 293.1c15.5-28 24.4-60.2 24.4-94.4C390.6 91 303 3.3 195.3 3.3S0 91 0 198.7 87.6 394 195.3 394c35.3 0 68.4-9.4 97-25.8l146.8 140.5zM55.8 198.7c0-76.9 62.6-139.5 139.5-139.5s139.5 62.6 139.5 139.5-62.6 139.5-139.5 139.5S55.8 275.6 55.8 198.7" style="fill:#3050ff"/></svg>

After

Width:  |  Height:  |  Size: 518 B

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