Grow the bundled template library to 83 homelab apps (0.43.0)
CI / build-and-push (push) Successful in 1m46s
CI / build-and-push (push) Successful in 1m46s
The library shipped five templates. This adds 78 more, covering what
homelab lists and the self-hosted community actually run: media servers
and the *arr automation chain, DNS ad-blocking, reverse proxies, VPN,
SSO, monitoring and dashboards, files/backup, notes and wikis, home
automation, dev tooling, databases, local AI, finance and notifications.
Every template follows the existing shape — compose.yaml, .env.example,
template.json — with PUID/PGID/TZ/DATA_PATH/HTTP_PORT knobs and no
literal secrets: anything that must be set uses ${VAR:?...} so deploy
fails loudly instead of coming up with a default password. Six ship the
extra config file their app needs (prometheus.yml, Caddyfile,
mosquitto.conf, frigate config.yml, Authelia's two files,
zigbee2mqtt configuration.yaml), which the folder-copy pull already
carries into the new stack.
All 95 referenced images were verified pullable against their
registries. Default host ports were deconflicted so several templates
can be pulled side by side; the only remaining overlaps are between
services you would never run together anyway (two DNS blockers on 53,
three reverse proxies on 80/443).
The Templates page would have been an unusable 83-card grid, so it now
has a search box and tag filter chips, with the tags on each card
clickable to filter by.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dk43rmEeRfYi5wsLDbmfyG
This commit is contained in:
@@ -76,11 +76,15 @@ as intuitive as Dockge, as capable as Portainer for Compose workflows.
|
||||
(`/proc/net/tcp[6]`) and running container bindings, with a confirm dialog.
|
||||
- **Resource limits**: CPU/memory sliders in the editor → `deploy.resources.limits`.
|
||||
- **Template library**: each template is a ready-to-run **stack folder** in git
|
||||
(`backend/templates/<slug>/` — `compose.yaml` + `.env.example` + `template.json`).
|
||||
Bundled set: Jellyfin, Vaultwarden, Uptime-Kuma, Paperless-NGX, Gitea. "Pull"
|
||||
copies the whole folder into a new stack (`.env.example` → `.env`) which you then
|
||||
edit and deploy. Save any stack back as a custom template (stored under
|
||||
`${DATA_DIR}/templates/`). Add your own by dropping a folder into the templates dir.
|
||||
(`backend/templates/<slug>/` — `compose.yaml` + `.env.example` + `template.json`,
|
||||
plus any extra config the app needs, e.g. `prometheus.yml` or a `Caddyfile`).
|
||||
83 bundled homelab apps across media, *arr automation, networking, reverse
|
||||
proxies, VPN, SSO, monitoring, dashboards, files/backup, notes and wikis, home
|
||||
automation, dev tooling, databases, local AI and more — searchable and
|
||||
filterable by tag on the Templates page. "Pull" copies the whole folder into a
|
||||
new stack (`.env.example` → `.env`) which you then edit and deploy. Save any
|
||||
stack back as a custom template (stored under `${DATA_DIR}/templates/`). Add
|
||||
your own by dropping a folder into the templates dir.
|
||||
- **Healthcheck status** surfaced per container in the stack overview.
|
||||
|
||||
### Phase 4 — Operations
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
TZ=Europe/Berlin
|
||||
DATA_PATH=/srv/actual
|
||||
HTTP_PORT=5006
|
||||
@@ -0,0 +1,11 @@
|
||||
services:
|
||||
actual:
|
||||
image: ghcr.io/actualbudget/actual-server:latest
|
||||
container_name: actual-budget
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- TZ=${TZ:-Europe/Berlin}
|
||||
ports:
|
||||
- "${HTTP_PORT:-5006}:5006"
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/actual}:/data
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "Actual Budget",
|
||||
"description": "Local-first envelope budgeting with end-to-end encrypted sync across devices.",
|
||||
"tags": [
|
||||
"finance",
|
||||
"productivity"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
DATA_PATH=/srv/adguardhome
|
||||
DNS_PORT=53
|
||||
SETUP_PORT=3300
|
||||
HTTP_PORT=8082
|
||||
@@ -0,0 +1,14 @@
|
||||
services:
|
||||
adguardhome:
|
||||
image: adguard/adguardhome:latest
|
||||
container_name: adguardhome
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${DNS_PORT:-53}:53/tcp"
|
||||
- "${DNS_PORT:-53}:53/udp"
|
||||
# Setup wizard on first run; the UI moves to HTTP_PORT afterwards.
|
||||
- "${SETUP_PORT:-3300}:3000/tcp"
|
||||
- "${HTTP_PORT:-8082}:80/tcp"
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/adguardhome}/work:/opt/adguardhome/work
|
||||
- ${DATA_PATH:-/srv/adguardhome}/conf:/opt/adguardhome/conf
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "AdGuard Home",
|
||||
"description": "DNS server with ad and tracker blocking, DoH/DoT and per-client rules.",
|
||||
"tags": [
|
||||
"network",
|
||||
"dns",
|
||||
"ad-blocking"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
TZ=Europe/Berlin
|
||||
DATA_PATH=/srv/audiobookshelf
|
||||
AUDIOBOOKS_PATH=/srv/media/audiobooks
|
||||
PODCASTS_PATH=/srv/media/podcasts
|
||||
HTTP_PORT=13378
|
||||
@@ -0,0 +1,14 @@
|
||||
services:
|
||||
audiobookshelf:
|
||||
image: ghcr.io/advplyr/audiobookshelf:latest
|
||||
container_name: audiobookshelf
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- TZ=${TZ:-Europe/Berlin}
|
||||
ports:
|
||||
- "${HTTP_PORT:-13378}:80"
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/audiobookshelf}/config:/config
|
||||
- ${DATA_PATH:-/srv/audiobookshelf}/metadata:/metadata
|
||||
- ${AUDIOBOOKS_PATH:-/srv/media/audiobooks}:/audiobooks
|
||||
- ${PODCASTS_PATH:-/srv/media/podcasts}:/podcasts
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "Audiobookshelf",
|
||||
"description": "Audiobook and podcast server that keeps progress in sync across devices.",
|
||||
"tags": [
|
||||
"media",
|
||||
"books",
|
||||
"streaming"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
TZ=Europe/Berlin
|
||||
DATA_PATH=/srv/authelia
|
||||
HTTP_PORT=9091
|
||||
@@ -0,0 +1,13 @@
|
||||
services:
|
||||
authelia:
|
||||
image: authelia/authelia:latest
|
||||
container_name: authelia
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- TZ=${TZ:-Europe/Berlin}
|
||||
ports:
|
||||
- "${HTTP_PORT:-9091}:9091"
|
||||
volumes:
|
||||
- ./configuration.yml:/config/configuration.yml:ro
|
||||
- ./users_database.yml:/config/users_database.yml
|
||||
- ${DATA_PATH:-/srv/authelia}:/config/db
|
||||
@@ -0,0 +1,34 @@
|
||||
# Minimal Authelia config. Replace every "change-me" and the example domains.
|
||||
theme: dark
|
||||
|
||||
identity_validation:
|
||||
reset_password:
|
||||
jwt_secret: change-me-jwt-secret
|
||||
|
||||
server:
|
||||
address: tcp://0.0.0.0:9091
|
||||
|
||||
authentication_backend:
|
||||
file:
|
||||
path: /config/users_database.yml
|
||||
|
||||
access_control:
|
||||
default_policy: deny
|
||||
rules:
|
||||
- domain: "*.example.com"
|
||||
policy: two_factor
|
||||
|
||||
session:
|
||||
secret: change-me-session-secret
|
||||
cookies:
|
||||
- domain: example.com
|
||||
authelia_url: https://auth.example.com
|
||||
|
||||
storage:
|
||||
encryption_key: change-me-encryption-key-at-least-20-chars
|
||||
local:
|
||||
path: /config/db/db.sqlite3
|
||||
|
||||
notifier:
|
||||
filesystem:
|
||||
filename: /config/db/notification.txt
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "Authelia",
|
||||
"description": "Lightweight authentication and 2FA portal for reverse-proxy forward auth.",
|
||||
"tags": [
|
||||
"security",
|
||||
"identity",
|
||||
"sso"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
# Generate a password hash with:
|
||||
# docker run --rm authelia/authelia:latest authelia crypto hash generate argon2 --password 'yourpassword'
|
||||
users:
|
||||
admin:
|
||||
disabled: false
|
||||
displayname: "Admin"
|
||||
password: "$argon2id$v=19$m=65536,t=3,p=4$REPLACE_ME"
|
||||
email: admin@example.com
|
||||
groups:
|
||||
- admins
|
||||
@@ -0,0 +1,7 @@
|
||||
DATA_PATH=/srv/authentik
|
||||
AUTHENTIK_TAG=2026.8.0
|
||||
HTTP_PORT=9200
|
||||
HTTPS_PORT=9243
|
||||
# Both required. Generate with: openssl rand -base64 36
|
||||
PG_PASS=change-me
|
||||
AUTHENTIK_SECRET_KEY=change-me
|
||||
@@ -0,0 +1,61 @@
|
||||
services:
|
||||
postgresql:
|
||||
image: postgres:16-alpine
|
||||
container_name: authentik-db
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- POSTGRES_DB=authentik
|
||||
- POSTGRES_USER=authentik
|
||||
- POSTGRES_PASSWORD=${PG_PASS:?database password required}
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -d authentik -U authentik"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 20s
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/authentik}/database:/var/lib/postgresql/data
|
||||
|
||||
server:
|
||||
image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2026.8.0}
|
||||
container_name: authentik-server
|
||||
command: server
|
||||
restart: unless-stopped
|
||||
shm_size: 512mb
|
||||
depends_on:
|
||||
postgresql:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
- AUTHENTIK_SECRET_KEY=${AUTHENTIK_SECRET_KEY:?secret key required}
|
||||
- AUTHENTIK_POSTGRESQL__HOST=postgresql
|
||||
- AUTHENTIK_POSTGRESQL__NAME=authentik
|
||||
- AUTHENTIK_POSTGRESQL__USER=authentik
|
||||
- AUTHENTIK_POSTGRESQL__PASSWORD=${PG_PASS}
|
||||
ports:
|
||||
- "${HTTP_PORT:-9200}:9000"
|
||||
- "${HTTPS_PORT:-9243}:9443"
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/authentik}/data:/data
|
||||
- ${DATA_PATH:-/srv/authentik}/custom-templates:/templates
|
||||
|
||||
worker:
|
||||
image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2026.8.0}
|
||||
container_name: authentik-worker
|
||||
command: worker
|
||||
restart: unless-stopped
|
||||
shm_size: 512mb
|
||||
user: root
|
||||
depends_on:
|
||||
postgresql:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
- AUTHENTIK_SECRET_KEY=${AUTHENTIK_SECRET_KEY}
|
||||
- AUTHENTIK_POSTGRESQL__HOST=postgresql
|
||||
- AUTHENTIK_POSTGRESQL__NAME=authentik
|
||||
- AUTHENTIK_POSTGRESQL__USER=authentik
|
||||
- AUTHENTIK_POSTGRESQL__PASSWORD=${PG_PASS}
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ${DATA_PATH:-/srv/authentik}/data:/data
|
||||
- ${DATA_PATH:-/srv/authentik}/certs:/certs
|
||||
- ${DATA_PATH:-/srv/authentik}/custom-templates:/templates
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "authentik",
|
||||
"description": "Identity provider and SSO gateway (OAuth2, SAML, LDAP, forward auth). Finish setup at /if/flow/initial-setup/.",
|
||||
"tags": [
|
||||
"security",
|
||||
"identity",
|
||||
"sso"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
PUID=1000
|
||||
PGID=1000
|
||||
TZ=Europe/Berlin
|
||||
DATA_PATH=/srv/bazarr
|
||||
MEDIA_PATH=/srv/media
|
||||
HTTP_PORT=6767
|
||||
@@ -0,0 +1,14 @@
|
||||
services:
|
||||
bazarr:
|
||||
image: lscr.io/linuxserver/bazarr:latest
|
||||
container_name: bazarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=${PUID:-1000}
|
||||
- PGID=${PGID:-1000}
|
||||
- TZ=${TZ:-Europe/Berlin}
|
||||
ports:
|
||||
- "${HTTP_PORT:-6767}:6767"
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/bazarr}:/config
|
||||
- ${MEDIA_PATH:-/srv/media}:/media
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "Bazarr",
|
||||
"description": "Companion to Sonarr and Radarr that downloads matching subtitles.",
|
||||
"tags": [
|
||||
"media",
|
||||
"automation",
|
||||
"arr"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
DATA_PATH=/srv/beszel
|
||||
HTTP_PORT=8090
|
||||
AGENT_PORT=45876
|
||||
AGENT_KEY=
|
||||
@@ -0,0 +1,22 @@
|
||||
services:
|
||||
beszel:
|
||||
image: henrygd/beszel:latest
|
||||
container_name: beszel
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${HTTP_PORT:-8090}:8090"
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/beszel}/data:/beszel_data
|
||||
|
||||
beszel-agent:
|
||||
image: henrygd/beszel-agent:latest
|
||||
container_name: beszel-agent
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
environment:
|
||||
- LISTEN=${AGENT_PORT:-45876}
|
||||
# Copy this from the "add system" dialog in the Beszel UI.
|
||||
- KEY=${AGENT_KEY:-}
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- ${DATA_PATH:-/srv/beszel}/agent:/var/lib/beszel-agent
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "Beszel",
|
||||
"description": "Lightweight server monitoring with historical charts, alerts and Docker stats.",
|
||||
"tags": [
|
||||
"monitoring",
|
||||
"metrics",
|
||||
"docker"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
PUID=1000
|
||||
PGID=1000
|
||||
TZ=Europe/Berlin
|
||||
DATA_PATH=/srv/bookstack
|
||||
HTTP_PORT=6875
|
||||
APP_URL=http://localhost:6875
|
||||
# Required, must be "base64:..." — generate with: echo "base64:$(openssl rand -base64 32)"
|
||||
APP_KEY=
|
||||
DB_PASSWORD=change-me
|
||||
DB_ROOT_PASSWORD=change-me
|
||||
@@ -0,0 +1,38 @@
|
||||
services:
|
||||
bookstack:
|
||||
image: lscr.io/linuxserver/bookstack:latest
|
||||
container_name: bookstack
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- bookstack-db
|
||||
environment:
|
||||
- PUID=${PUID:-1000}
|
||||
- PGID=${PGID:-1000}
|
||||
- TZ=${TZ:-Europe/Berlin}
|
||||
- APP_URL=${APP_URL:-http://localhost:6875}
|
||||
# Required. Generate with: openssl rand -base64 32
|
||||
- APP_KEY=${APP_KEY:?app key required}
|
||||
- DB_HOST=bookstack-db
|
||||
- DB_PORT=3306
|
||||
- DB_DATABASE=bookstackapp
|
||||
- DB_USERNAME=bookstack
|
||||
- DB_PASSWORD=${DB_PASSWORD:-bookstack}
|
||||
ports:
|
||||
- "${HTTP_PORT:-6875}:80"
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/bookstack}/config:/config
|
||||
|
||||
bookstack-db:
|
||||
image: lscr.io/linuxserver/mariadb:latest
|
||||
container_name: bookstack-db
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=${PUID:-1000}
|
||||
- PGID=${PGID:-1000}
|
||||
- TZ=${TZ:-Europe/Berlin}
|
||||
- MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD:-bookstack}
|
||||
- MYSQL_DATABASE=bookstackapp
|
||||
- MYSQL_USER=bookstack
|
||||
- MYSQL_PASSWORD=${DB_PASSWORD:-bookstack}
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/bookstack}/db:/config
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "BookStack",
|
||||
"description": "Documentation platform organised into shelves, books, chapters and pages. First login: admin@admin.com / password.",
|
||||
"tags": [
|
||||
"documents",
|
||||
"wiki",
|
||||
"productivity"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
DATA_PATH=/srv/caddy
|
||||
HTTP_PORT=80
|
||||
HTTPS_PORT=443
|
||||
@@ -0,0 +1,11 @@
|
||||
# Caddy issues and renews TLS certificates automatically for any real hostname.
|
||||
# Replace the examples below with your own, then restart the stack.
|
||||
|
||||
app.example.com {
|
||||
reverse_proxy host.docker.internal:8080
|
||||
}
|
||||
|
||||
# Local-only site on plain HTTP (no certificate needed):
|
||||
# http://nas.lan {
|
||||
# reverse_proxy 192.168.1.10:5000
|
||||
# }
|
||||
@@ -0,0 +1,13 @@
|
||||
services:
|
||||
caddy:
|
||||
image: caddy:2-alpine
|
||||
container_name: caddy
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${HTTP_PORT:-80}:80"
|
||||
- "${HTTPS_PORT:-443}:443"
|
||||
- "${HTTPS_PORT:-443}:443/udp"
|
||||
volumes:
|
||||
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
||||
- ${DATA_PATH:-/srv/caddy}/data:/data
|
||||
- ${DATA_PATH:-/srv/caddy}/config:/config
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "Caddy",
|
||||
"description": "Reverse proxy with automatic HTTPS, configured through a short Caddyfile.",
|
||||
"tags": [
|
||||
"network",
|
||||
"proxy"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
PUID=1000
|
||||
PGID=1000
|
||||
TZ=Europe/Berlin
|
||||
DATA_PATH=/srv/calibre-web
|
||||
LIBRARY_PATH=/srv/media/books
|
||||
HTTP_PORT=8083
|
||||
@@ -0,0 +1,16 @@
|
||||
services:
|
||||
calibre-web:
|
||||
image: lscr.io/linuxserver/calibre-web:latest
|
||||
container_name: calibre-web
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=${PUID:-1000}
|
||||
- PGID=${PGID:-1000}
|
||||
- TZ=${TZ:-Europe/Berlin}
|
||||
# Adds ebook format conversion (downloads Calibre on first start)
|
||||
- DOCKER_MODS=linuxserver/mods:universal-calibre
|
||||
ports:
|
||||
- "${HTTP_PORT:-8083}:8083"
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/calibre-web}:/config
|
||||
- ${LIBRARY_PATH:-/srv/media/books}:/books
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "Calibre-Web",
|
||||
"description": "Web front-end for a Calibre ebook library, with OPDS and send-to-Kindle.",
|
||||
"tags": [
|
||||
"media",
|
||||
"books"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
DATA_PATH=/srv/changedetection
|
||||
HTTP_PORT=5000
|
||||
BASE_URL=http://localhost:5000
|
||||
@@ -0,0 +1,25 @@
|
||||
services:
|
||||
changedetection:
|
||||
image: ghcr.io/dgtlmoon/changedetection.io:latest
|
||||
container_name: changedetection
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- BASE_URL=${BASE_URL:-http://localhost:5000}
|
||||
- PLAYWRIGHT_DRIVER_URL=ws://browser:3000
|
||||
ports:
|
||||
- "${HTTP_PORT:-5000}:5000"
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/changedetection}:/datastore
|
||||
depends_on:
|
||||
- browser
|
||||
|
||||
browser:
|
||||
image: dgtlmoon/sockpuppetbrowser:latest
|
||||
container_name: changedetection-browser
|
||||
restart: unless-stopped
|
||||
cap_add:
|
||||
- SYS_ADMIN
|
||||
environment:
|
||||
- SCREEN_WIDTH=1920
|
||||
- SCREEN_HEIGHT=1024
|
||||
- MAX_CONCURRENT_CHROME_PROCESSES=10
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "changedetection.io",
|
||||
"description": "Watches web pages for changes and notifies you — with a headless browser for JS-heavy sites.",
|
||||
"tags": [
|
||||
"monitoring",
|
||||
"automation"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
PUID=1000
|
||||
PGID=1000
|
||||
TZ=Europe/Berlin
|
||||
DATA_PATH=/srv/code-server
|
||||
PROJECTS_PATH=/srv/projects
|
||||
HTTP_PORT=8443
|
||||
# Required — this is the web login password.
|
||||
PASSWORD=
|
||||
SUDO_PASSWORD=
|
||||
@@ -0,0 +1,17 @@
|
||||
services:
|
||||
code-server:
|
||||
image: lscr.io/linuxserver/code-server:latest
|
||||
container_name: code-server
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=${PUID:-1000}
|
||||
- PGID=${PGID:-1000}
|
||||
- TZ=${TZ:-Europe/Berlin}
|
||||
- PASSWORD=${PASSWORD:?password required}
|
||||
- SUDO_PASSWORD=${SUDO_PASSWORD:-}
|
||||
- DEFAULT_WORKSPACE=/config/workspace
|
||||
ports:
|
||||
- "${HTTP_PORT:-8443}:8443"
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/code-server}:/config
|
||||
- ${PROJECTS_PATH:-/srv/projects}:/config/workspace
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "code-server",
|
||||
"description": "VS Code in the browser, running on the server where your files already are.",
|
||||
"tags": [
|
||||
"dev"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
DATA_PATH=/srv/dashy
|
||||
HTTP_PORT=4000
|
||||
@@ -0,0 +1,12 @@
|
||||
services:
|
||||
dashy:
|
||||
image: lissy93/dashy:latest
|
||||
container_name: dashy
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
ports:
|
||||
- "${HTTP_PORT:-4000}:8080"
|
||||
volumes:
|
||||
# Dashy writes conf.yml back into this directory when you edit in the UI.
|
||||
- ${DATA_PATH:-/srv/dashy}:/app/user-data
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "Dashy",
|
||||
"description": "Highly themeable dashboard with status checks, editable from the browser.",
|
||||
"tags": [
|
||||
"dashboard"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
DATA_PATH=/srv/registry
|
||||
HTTP_PORT=5050
|
||||
UI_PORT=5080
|
||||
REGISTRY_TITLE=Homelab Registry
|
||||
@@ -0,0 +1,29 @@
|
||||
services:
|
||||
registry:
|
||||
image: registry:2
|
||||
container_name: registry
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- REGISTRY_STORAGE_DELETE_ENABLED=true
|
||||
ports:
|
||||
- "${HTTP_PORT:-5050}:5000"
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/registry}:/var/lib/registry
|
||||
# Basic auth. Create it with:
|
||||
# docker run --rm httpd:alpine htpasswd -Bbn user pass > htpasswd
|
||||
# then uncomment the mount and the three REGISTRY_AUTH_* vars above.
|
||||
# - ./htpasswd:/auth/htpasswd:ro
|
||||
|
||||
registry-ui:
|
||||
image: joxit/docker-registry-ui:latest
|
||||
container_name: registry-ui
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- registry
|
||||
environment:
|
||||
- SINGLE_REGISTRY=true
|
||||
- REGISTRY_TITLE=${REGISTRY_TITLE:-Homelab Registry}
|
||||
- NGINX_PROXY_PASS_URL=http://registry:5000
|
||||
- DELETE_IMAGES=true
|
||||
ports:
|
||||
- "${UI_PORT:-5080}:80"
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "Docker Registry",
|
||||
"description": "Private container registry with a browsable web UI. Add auth and TLS before exposing it.",
|
||||
"tags": [
|
||||
"docker",
|
||||
"dev"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
DATA_PATH=/srv/dockge
|
||||
STACKS_DIR=/opt/stacks
|
||||
HTTP_PORT=5001
|
||||
@@ -0,0 +1,14 @@
|
||||
services:
|
||||
dockge:
|
||||
image: louislam/dockge:1
|
||||
container_name: dockge
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- DOCKGE_STACKS_DIR=${STACKS_DIR:-/opt/stacks}
|
||||
ports:
|
||||
- "${HTTP_PORT:-5001}:5001"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ${DATA_PATH:-/srv/dockge}:/app/data
|
||||
# Host path and container path must match, or compose lookups break.
|
||||
- ${STACKS_DIR:-/opt/stacks}:${STACKS_DIR:-/opt/stacks}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "Dockge",
|
||||
"description": "Compose-stack manager with a live editor and terminal output.",
|
||||
"tags": [
|
||||
"docker",
|
||||
"dashboard"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
HTTP_PORT=8888
|
||||
@@ -0,0 +1,12 @@
|
||||
services:
|
||||
dozzle:
|
||||
image: amir20/dozzle:latest
|
||||
container_name: dozzle
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- DOZZLE_LEVEL=info
|
||||
- DOZZLE_NO_ANALYTICS=true
|
||||
ports:
|
||||
- "${HTTP_PORT:-8888}:8080"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "Dozzle",
|
||||
"description": "Live container log viewer in the browser — no log shipping, no storage.",
|
||||
"tags": [
|
||||
"monitoring",
|
||||
"docker",
|
||||
"logs"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
PUID=1000
|
||||
PGID=1000
|
||||
TZ=Europe/Berlin
|
||||
DATA_PATH=/srv/duplicati
|
||||
BACKUPS_PATH=/srv/backups
|
||||
SOURCE_PATH=/srv
|
||||
HTTP_PORT=8201
|
||||
WEB_PASSWORD=change-me
|
||||
# Required. Generate with: openssl rand -hex 32
|
||||
SETTINGS_ENCRYPTION_KEY=
|
||||
@@ -0,0 +1,17 @@
|
||||
services:
|
||||
duplicati:
|
||||
image: lscr.io/linuxserver/duplicati:latest
|
||||
container_name: duplicati
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=${PUID:-1000}
|
||||
- PGID=${PGID:-1000}
|
||||
- TZ=${TZ:-Europe/Berlin}
|
||||
- SETTINGS_ENCRYPTION_KEY=${SETTINGS_ENCRYPTION_KEY:?encryption key required}
|
||||
- DUPLICATI__WEBSERVICE_PASSWORD=${WEB_PASSWORD:-change-me}
|
||||
ports:
|
||||
- "${HTTP_PORT:-8201}:8200"
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/duplicati}:/config
|
||||
- ${BACKUPS_PATH:-/srv/backups}:/backups
|
||||
- ${SOURCE_PATH:-/srv}:/source:ro
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "Duplicati",
|
||||
"description": "Scheduled, encrypted, deduplicated backups to local disks or any cloud target.",
|
||||
"tags": [
|
||||
"backup",
|
||||
"files"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
PUID=1000
|
||||
PGID=1000
|
||||
TZ=Europe/Berlin
|
||||
CONFIG_PATH=/srv/emby/config
|
||||
MEDIA_PATH=/srv/media
|
||||
HTTP_PORT=8105
|
||||
@@ -0,0 +1,17 @@
|
||||
services:
|
||||
emby:
|
||||
image: lscr.io/linuxserver/emby:latest
|
||||
container_name: emby
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=${PUID:-1000}
|
||||
- PGID=${PGID:-1000}
|
||||
- TZ=${TZ:-Europe/Berlin}
|
||||
ports:
|
||||
- "${HTTP_PORT:-8105}:8096"
|
||||
volumes:
|
||||
- ${CONFIG_PATH:-/srv/emby/config}:/config
|
||||
- ${MEDIA_PATH:-/srv/media}:/media
|
||||
# Uncomment for Intel/AMD hardware transcoding (Emby Premiere required):
|
||||
# devices:
|
||||
# - /dev/dri:/dev/dri
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "Emby",
|
||||
"description": "Media server for movies, TV and music, with live TV and DVR support.",
|
||||
"tags": [
|
||||
"media",
|
||||
"streaming"
|
||||
],
|
||||
"gpu": "NVIDIA / Intel optional"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
TZ=Europe/Berlin
|
||||
DATA_PATH=/srv/esphome
|
||||
# Optional basic auth for the dashboard.
|
||||
USERNAME=
|
||||
PASSWORD=
|
||||
# Runs on host networking — the UI is on port 6052 of the host itself.
|
||||
@@ -0,0 +1,15 @@
|
||||
services:
|
||||
esphome:
|
||||
image: ghcr.io/esphome/esphome:latest
|
||||
container_name: esphome
|
||||
restart: unless-stopped
|
||||
# Host networking is needed for OTA discovery of your devices.
|
||||
network_mode: host
|
||||
privileged: true
|
||||
environment:
|
||||
- TZ=${TZ:-Europe/Berlin}
|
||||
- USERNAME=${USERNAME:-}
|
||||
- PASSWORD=${PASSWORD:-}
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/esphome}:/config
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "ESPHome",
|
||||
"description": "Build and flash firmware for ESP32/ESP8266 sensors straight from the browser.",
|
||||
"tags": [
|
||||
"home-automation",
|
||||
"iot",
|
||||
"dev"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
PUID=1000
|
||||
PGID=1000
|
||||
DATA_PATH=/srv/filebrowser
|
||||
FILES_PATH=/srv
|
||||
HTTP_PORT=8088
|
||||
@@ -0,0 +1,16 @@
|
||||
services:
|
||||
filebrowser:
|
||||
# Pinned to the v2 line — v3 changes the on-disk layout.
|
||||
image: filebrowser/filebrowser:v2
|
||||
container_name: filebrowser
|
||||
restart: unless-stopped
|
||||
user: "${PUID:-1000}:${PGID:-1000}"
|
||||
environment:
|
||||
- FB_ROOT=/srv
|
||||
- FB_DATABASE=/database/filebrowser.db
|
||||
- FB_PORT=80
|
||||
ports:
|
||||
- "${HTTP_PORT:-8088}:80"
|
||||
volumes:
|
||||
- ${FILES_PATH:-/srv}:/srv
|
||||
- ${DATA_PATH:-/srv/filebrowser}/database:/database
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "File Browser",
|
||||
"description": "Web file manager for a directory tree. Default login admin/admin — change it immediately.",
|
||||
"tags": [
|
||||
"files"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
TZ=Europe/Berlin
|
||||
DATA_PATH=/srv/firefly-iii
|
||||
HTTP_PORT=8104
|
||||
APP_URL=http://localhost:8104
|
||||
# Required, exactly 32 characters. Generate with: openssl rand -hex 16
|
||||
APP_KEY=
|
||||
DB_PASSWORD=change-me
|
||||
@@ -0,0 +1,37 @@
|
||||
services:
|
||||
app:
|
||||
image: fireflyiii/core:latest
|
||||
container_name: firefly-iii
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- db
|
||||
environment:
|
||||
- TZ=${TZ:-Europe/Berlin}
|
||||
- APP_ENV=production
|
||||
- APP_URL=${APP_URL:-http://localhost:8095}
|
||||
# Required, exactly 32 characters. Generate with: openssl rand -hex 16
|
||||
- APP_KEY=${APP_KEY:?app key required, exactly 32 characters}
|
||||
- TRUSTED_PROXIES=**
|
||||
- DB_CONNECTION=mysql
|
||||
- DB_HOST=db
|
||||
- DB_PORT=3306
|
||||
- DB_DATABASE=firefly
|
||||
- DB_USERNAME=firefly
|
||||
- DB_PASSWORD=${DB_PASSWORD:-firefly}
|
||||
ports:
|
||||
- "${HTTP_PORT:-8104}:8080"
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/firefly-iii}/upload:/var/www/html/storage/upload
|
||||
|
||||
db:
|
||||
image: mariadb:11
|
||||
container_name: firefly-iii-db
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- MARIADB_AUTO_UPGRADE=1
|
||||
- MYSQL_DATABASE=firefly
|
||||
- MYSQL_USER=firefly
|
||||
- MYSQL_PASSWORD=${DB_PASSWORD:-firefly}
|
||||
- MYSQL_RANDOM_ROOT_PASSWORD=yes
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/firefly-iii}/db:/var/lib/mysql
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "Firefly III",
|
||||
"description": "Double-entry personal finance manager with budgets, rules and reports.",
|
||||
"tags": [
|
||||
"finance",
|
||||
"productivity"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
PUID=1000
|
||||
PGID=1000
|
||||
DATA_PATH=/srv/forgejo
|
||||
HTTP_PORT=3301
|
||||
SSH_PORT=2223
|
||||
ROOT_URL=http://localhost:3000/
|
||||
DOMAIN=localhost
|
||||
@@ -0,0 +1,17 @@
|
||||
services:
|
||||
forgejo:
|
||||
image: codeberg.org/forgejo/forgejo:16
|
||||
container_name: forgejo
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- USER_UID=${PUID:-1000}
|
||||
- USER_GID=${PGID:-1000}
|
||||
- FORGEJO__server__ROOT_URL=${ROOT_URL:-http://localhost:3000/}
|
||||
- FORGEJO__server__DOMAIN=${DOMAIN:-localhost}
|
||||
ports:
|
||||
- "${HTTP_PORT:-3301}:3000"
|
||||
- "${SSH_PORT:-2223}:22"
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/forgejo}:/data
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "Forgejo",
|
||||
"description": "Community-run Git forge with CI (Forgejo Actions) — the Gitea fork.",
|
||||
"tags": [
|
||||
"git",
|
||||
"dev"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
TZ=Europe/Berlin
|
||||
DATA_PATH=/srv/freshrss
|
||||
HTTP_PORT=8093
|
||||
CRON_MIN=*/20
|
||||
@@ -0,0 +1,13 @@
|
||||
services:
|
||||
freshrss:
|
||||
image: freshrss/freshrss:latest
|
||||
container_name: freshrss
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- TZ=${TZ:-Europe/Berlin}
|
||||
- CRON_MIN=${CRON_MIN:-*/20}
|
||||
ports:
|
||||
- "${HTTP_PORT:-8093}:80"
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/freshrss}/data:/var/www/FreshRSS/data
|
||||
- ${DATA_PATH:-/srv/freshrss}/extensions:/var/www/FreshRSS/extensions
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "FreshRSS",
|
||||
"description": "Self-hosted RSS aggregator with an API for mobile readers, SQLite by default.",
|
||||
"tags": [
|
||||
"rss",
|
||||
"productivity"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
TZ=Europe/Berlin
|
||||
DATA_PATH=/srv/frigate
|
||||
MEDIA_PATH=/srv/frigate/media
|
||||
HTTP_PORT=8971
|
||||
RTSP_PORT=8554
|
||||
WEBRTC_PORT=8555
|
||||
SHM_SIZE=256mb
|
||||
RTSP_PASSWORD=change-me
|
||||
@@ -0,0 +1,32 @@
|
||||
services:
|
||||
frigate:
|
||||
image: ghcr.io/blakeblackshear/frigate:stable
|
||||
container_name: frigate
|
||||
restart: unless-stopped
|
||||
privileged: true
|
||||
shm_size: ${SHM_SIZE:-256mb}
|
||||
environment:
|
||||
- TZ=${TZ:-Europe/Berlin}
|
||||
- FRIGATE_RTSP_PASSWORD=${RTSP_PASSWORD:-change-me}
|
||||
ports:
|
||||
- "${HTTP_PORT:-8971}:8971"
|
||||
- "${RTSP_PORT:-8554}:8554"
|
||||
- "${WEBRTC_PORT:-8555}:8555/tcp"
|
||||
- "${WEBRTC_PORT:-8555}:8555/udp"
|
||||
volumes:
|
||||
# The config lives with the stack so you can edit it here; the directory
|
||||
# underneath holds Frigate's database and model cache.
|
||||
- ${DATA_PATH:-/srv/frigate}/config:/config
|
||||
- ./config.yml:/config/config.yml
|
||||
- ${MEDIA_PATH:-/srv/frigate/media}:/media/frigate
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- type: tmpfs
|
||||
target: /tmp/cache
|
||||
tmpfs:
|
||||
size: 1000000000
|
||||
# Uncomment what your host actually has:
|
||||
# devices:
|
||||
# # Google Coral USB accelerator
|
||||
# - /dev/bus/usb:/dev/bus/usb
|
||||
# # Intel iGPU for hardware decoding
|
||||
# - /dev/dri/renderD128:/dev/dri/renderD128
|
||||
@@ -0,0 +1,38 @@
|
||||
mqtt:
|
||||
enabled: false
|
||||
|
||||
detectors:
|
||||
cpu1:
|
||||
type: cpu
|
||||
# Swap for a Coral TPU once you have one:
|
||||
# coral:
|
||||
# type: edgetpu
|
||||
# device: usb
|
||||
|
||||
cameras:
|
||||
front_door:
|
||||
ffmpeg:
|
||||
inputs:
|
||||
- path: rtsp://user:{FRIGATE_RTSP_PASSWORD}@192.168.1.50:554/stream1
|
||||
roles:
|
||||
- detect
|
||||
- record
|
||||
detect:
|
||||
width: 1280
|
||||
height: 720
|
||||
fps: 5
|
||||
objects:
|
||||
track:
|
||||
- person
|
||||
- car
|
||||
|
||||
record:
|
||||
enabled: true
|
||||
retain:
|
||||
days: 7
|
||||
mode: motion
|
||||
|
||||
snapshots:
|
||||
enabled: true
|
||||
retain:
|
||||
default: 14
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "Frigate NVR",
|
||||
"description": "Network video recorder with real-time object detection. Edit config.yml with your cameras before deploying.",
|
||||
"tags": [
|
||||
"home-automation",
|
||||
"video",
|
||||
"monitoring"
|
||||
],
|
||||
"gpu": "Coral TPU / Intel / NVIDIA optional"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
TZ=Europe/Berlin
|
||||
DATA_PATH=/srv/gotify
|
||||
HTTP_PORT=8098
|
||||
ADMIN_USER=admin
|
||||
# Required.
|
||||
ADMIN_PASSWORD=
|
||||
@@ -0,0 +1,13 @@
|
||||
services:
|
||||
gotify:
|
||||
image: gotify/server:latest
|
||||
container_name: gotify
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- TZ=${TZ:-Europe/Berlin}
|
||||
- GOTIFY_DEFAULTUSER_NAME=${ADMIN_USER:-admin}
|
||||
- GOTIFY_DEFAULTUSER_PASS=${ADMIN_PASSWORD:?admin password required}
|
||||
ports:
|
||||
- "${HTTP_PORT:-8098}:80"
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/gotify}:/app/data
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "Gotify",
|
||||
"description": "Simple push notification server with per-application tokens and an Android app.",
|
||||
"tags": [
|
||||
"notifications",
|
||||
"monitoring"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
PUID=1000
|
||||
PGID=1000
|
||||
DATA_PATH=/srv/grafana
|
||||
HTTP_PORT=3030
|
||||
ROOT_URL=http://localhost:3000
|
||||
ADMIN_USER=admin
|
||||
ADMIN_PASSWORD=change-me
|
||||
INSTALL_PLUGINS=
|
||||
@@ -0,0 +1,15 @@
|
||||
services:
|
||||
grafana:
|
||||
image: grafana/grafana:latest
|
||||
container_name: grafana
|
||||
restart: unless-stopped
|
||||
user: "${PUID:-1000}:${PGID:-1000}"
|
||||
environment:
|
||||
- GF_SECURITY_ADMIN_USER=${ADMIN_USER:-admin}
|
||||
- GF_SECURITY_ADMIN_PASSWORD=${ADMIN_PASSWORD:-change-me}
|
||||
- GF_SERVER_ROOT_URL=${ROOT_URL:-http://localhost:3000}
|
||||
- GF_INSTALL_PLUGINS=${INSTALL_PLUGINS:-}
|
||||
ports:
|
||||
- "${HTTP_PORT:-3030}:3000"
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/grafana}:/var/lib/grafana
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "Grafana",
|
||||
"description": "Dashboards and alerting on top of Prometheus, InfluxDB, Loki and friends.",
|
||||
"tags": [
|
||||
"monitoring",
|
||||
"metrics",
|
||||
"dashboard"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
PUID=1000
|
||||
PGID=1000
|
||||
TZ=Europe/Berlin
|
||||
DATA_PATH=/srv/grocy
|
||||
HTTP_PORT=9283
|
||||
@@ -0,0 +1,13 @@
|
||||
services:
|
||||
grocy:
|
||||
image: lscr.io/linuxserver/grocy:latest
|
||||
container_name: grocy
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=${PUID:-1000}
|
||||
- PGID=${PGID:-1000}
|
||||
- TZ=${TZ:-Europe/Berlin}
|
||||
ports:
|
||||
- "${HTTP_PORT:-9283}:80"
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/grocy}:/config
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "Grocy",
|
||||
"description": "Groceries, stock, chores and household ERP with barcode scanning. First login: admin / admin.",
|
||||
"tags": [
|
||||
"productivity",
|
||||
"recipes"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
PUID=1000
|
||||
PGID=1000
|
||||
TZ=Europe/Berlin
|
||||
DATA_PATH=/srv/heimdall
|
||||
HTTP_PORT=8102
|
||||
HTTPS_PORT=8103
|
||||
@@ -0,0 +1,14 @@
|
||||
services:
|
||||
heimdall:
|
||||
image: lscr.io/linuxserver/heimdall:latest
|
||||
container_name: heimdall
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=${PUID:-1000}
|
||||
- PGID=${PGID:-1000}
|
||||
- TZ=${TZ:-Europe/Berlin}
|
||||
ports:
|
||||
- "${HTTP_PORT:-8102}:80"
|
||||
- "${HTTPS_PORT:-8103}:443"
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/heimdall}:/config
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "Heimdall",
|
||||
"description": "Simple application dashboard with enhanced tiles for common services.",
|
||||
"tags": [
|
||||
"dashboard"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
DATA_PATH=/srv/homarr
|
||||
HTTP_PORT=7575
|
||||
# Required. Generate with: openssl rand -hex 32
|
||||
SECRET_ENCRYPTION_KEY=
|
||||
@@ -0,0 +1,14 @@
|
||||
services:
|
||||
homarr:
|
||||
image: ghcr.io/homarr-labs/homarr:latest
|
||||
container_name: homarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
# Required. Generate with: openssl rand -hex 32
|
||||
- SECRET_ENCRYPTION_KEY=${SECRET_ENCRYPTION_KEY:?encryption key required}
|
||||
ports:
|
||||
- "${HTTP_PORT:-7575}:7575"
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/homarr}:/appdata
|
||||
# Optional: lets Homarr show container status
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "Homarr",
|
||||
"description": "Drag-and-drop dashboard with integrations for the *arr apps, Docker and more.",
|
||||
"tags": [
|
||||
"dashboard"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
TZ=Europe/Berlin
|
||||
DATA_PATH=/srv/homeassistant
|
||||
# Runs on host networking — the UI is on port 8123 of the host itself.
|
||||
@@ -0,0 +1,17 @@
|
||||
services:
|
||||
homeassistant:
|
||||
image: ghcr.io/home-assistant/home-assistant:stable
|
||||
container_name: homeassistant
|
||||
restart: unless-stopped
|
||||
# Host networking lets HA discover devices via mDNS, SSDP and DHCP.
|
||||
# Swap it for a ports mapping if you only use cloud/MQTT integrations.
|
||||
network_mode: host
|
||||
privileged: true
|
||||
environment:
|
||||
- TZ=${TZ:-Europe/Berlin}
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/homeassistant}:/config
|
||||
- /run/dbus:/run/dbus:ro
|
||||
# Uncomment to pass through a Zigbee/Z-Wave USB stick:
|
||||
# devices:
|
||||
# - /dev/ttyUSB0:/dev/ttyUSB0
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "Home Assistant",
|
||||
"description": "Home automation hub with thousands of integrations. Runs on host networking for device discovery.",
|
||||
"tags": [
|
||||
"home-automation",
|
||||
"iot"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
PUID=1000
|
||||
PGID=1000
|
||||
DATA_PATH=/srv/homepage
|
||||
HTTP_PORT=3005
|
||||
ALLOWED_HOSTS=*
|
||||
@@ -0,0 +1,15 @@
|
||||
services:
|
||||
homepage:
|
||||
image: ghcr.io/gethomepage/homepage:latest
|
||||
container_name: homepage
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=${PUID:-1000}
|
||||
- PGID=${PGID:-1000}
|
||||
# Comma-separated hostnames the UI may be reached under, or "*" to allow all.
|
||||
- HOMEPAGE_ALLOWED_HOSTS=${ALLOWED_HOSTS:-*}
|
||||
ports:
|
||||
- "${HTTP_PORT:-3005}:3000"
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/homepage}:/app/config
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "Homepage",
|
||||
"description": "YAML-configured start page with live widgets for dozens of self-hosted services.",
|
||||
"tags": [
|
||||
"dashboard"
|
||||
],
|
||||
"gpu": null
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
TZ=Europe/Berlin
|
||||
IMMICH_VERSION=release
|
||||
DATA_PATH=/srv/immich
|
||||
# Where uploaded photos and videos live. Network shares are fine here.
|
||||
UPLOAD_LOCATION=/srv/immich/library
|
||||
# The database must sit on local storage — never on NFS/SMB.
|
||||
DB_DATA_LOCATION=/srv/immich/postgres
|
||||
DB_USERNAME=postgres
|
||||
DB_PASSWORD=change-me
|
||||
DB_DATABASE_NAME=immich
|
||||
HTTP_PORT=2283
|
||||
@@ -0,0 +1,51 @@
|
||||
services:
|
||||
immich-server:
|
||||
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
|
||||
container_name: immich-server
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- redis
|
||||
- database
|
||||
environment:
|
||||
- TZ=${TZ:-Europe/Berlin}
|
||||
- DB_HOSTNAME=database
|
||||
- DB_USERNAME=${DB_USERNAME:-postgres}
|
||||
- DB_PASSWORD=${DB_PASSWORD:-postgres}
|
||||
- DB_DATABASE_NAME=${DB_DATABASE_NAME:-immich}
|
||||
- REDIS_HOSTNAME=redis
|
||||
ports:
|
||||
- "${HTTP_PORT:-2283}:2283"
|
||||
volumes:
|
||||
- ${UPLOAD_LOCATION:-/srv/immich/library}:/data
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
# Uncomment for Intel/AMD hardware transcoding:
|
||||
# devices:
|
||||
# - /dev/dri:/dev/dri
|
||||
|
||||
immich-machine-learning:
|
||||
# Add -cuda / -openvino / -rocm to the tag for accelerated inference.
|
||||
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
|
||||
container_name: immich-machine-learning
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ${DATA_PATH:-/srv/immich}/model-cache:/cache
|
||||
|
||||
redis:
|
||||
image: valkey/valkey:8-alpine
|
||||
container_name: immich-redis
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: redis-cli ping | grep -q PONG || exit 1
|
||||
|
||||
database:
|
||||
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0
|
||||
container_name: immich-postgres
|
||||
restart: unless-stopped
|
||||
shm_size: 128mb
|
||||
environment:
|
||||
- POSTGRES_USER=${DB_USERNAME:-postgres}
|
||||
- POSTGRES_PASSWORD=${DB_PASSWORD:-postgres}
|
||||
- POSTGRES_DB=${DB_DATABASE_NAME:-immich}
|
||||
- POSTGRES_INITDB_ARGS=--data-checksums
|
||||
volumes:
|
||||
- ${DB_DATA_LOCATION:-/srv/immich/postgres}:/var/lib/postgresql/data
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user