first commit

This commit is contained in:
Fern Garden 2025-06-24 15:00:31 +08:00
commit 149e02a10d
72 changed files with 3442 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
**/.env

17
13ft/compose.yaml Normal file
View file

@ -0,0 +1,17 @@
services:
13ft:
container_name: 13ft
image: ghcr.io/wasi-master/13ft:latest
restart: unless-stopped
networks:
- default
- proxy
labels:
caddy: 13ft.ferngarden.net
caddy.import: internal
caddy.reverse_proxy: '{{ upstreams 5000 }}'
networks:
default:
proxy:
external: true

3
arr/README.md Normal file
View file

@ -0,0 +1,3 @@
# Compose file for the *arr stack
## Environment Variables
- QBITTORRENT_PASSWORD - qBittorrent password for cleanuperr

304
arr/compose.yaml Normal file
View file

@ -0,0 +1,304 @@
services:
jellyseerr:
image: ghcr.io/fallenbagel/jellyseerr:latest
container_name: jellyseerr
networks:
- default
- proxy
- media
environment:
- LOG_LEVEL=debug
- TZ=Australia/Perth
volumes:
- jellyseerr_config:/app/config
restart: unless-stopped
labels:
caddy: jellyseerr.fern.garden
caddy.import: internal
caddy.reverse_proxy: "{{upstreams 5055}}"
jackett:
image: lscr.io/linuxserver/jackett:latest
container_name: jackett
networks:
- default
- media
- proxy
environment:
- PUID=1000
- PGID=1800
- TZ=Australia/Perth
volumes:
- jackett_config:/config
- jackett_downloads:/downloads
restart: unless-stopped
labels:
caddy: jackett.ferngarden.net
caddy.1_import: internal
caddy.2_import: authentik
prowlarr:
image: lscr.io/linuxserver/prowlarr:latest
container_name: prowlarr
networks:
- default
- media
- proxy
environment:
- PUID=1000
- PGID=1800
- TZ=Australia/Perth
volumes:
- prowlarr_config:/config
restart: unless-stopped
labels:
caddy: prowlarr.ferngarden.net
caddy.1_import: internal
caddy.2_import: authentik
flaresolverr:
image: ghcr.io/flaresolverr/flaresolverr:latest
container_name: flaresolverr
networks:
- default
environment:
- LOG_LEVEL=info
- LOG_HTML=false
- CAPTCHA_SOLVER=none
- TZ=Australia/Perth
restart: unless-stopped
bazarr:
image: lscr.io/linuxserver/bazarr:latest
container_name: bazarr
networks:
- default
- media
- proxy
environment:
- PUID=1000
- PGID=1800
- TZ=Australia/Perth
volumes:
- bazarr_config:/config
- /media:/media
restart: unless-stopped
labels:
caddy: bazarr.ferngarden.net
caddy.1_import: internal
caddy.2_import: authentik
sonarr:
image: lscr.io/linuxserver/sonarr:latest
container_name: sonarr
networks:
- default
- media
- proxy
environment:
- PUID=1000
- PGID=1800
- TZ=Australia/Perth
volumes:
- sonarr_config:/config
- /media:/media
restart: unless-stopped
labels:
caddy: sonarr.ferngarden.net
caddy.1_import: internal
caddy.2_import: authentik
radarr:
image: lscr.io/linuxserver/radarr:latest
container_name: radarr
networks:
- default
- media
- proxy
environment:
- PUID=1000
- PGID=1800
- TZ=Australia/Perth
volumes:
- radarr_config:/config
- /media:/media
restart: unless-stopped
labels:
caddy: radarr.ferngarden.net
caddy.1_import: internal
caddy.2_import: authentik
lidarr:
image: blampe/lidarr:latest
container_name: lidarr
networks:
- default
- media
- proxy
environment:
- PUID=1000
- PGID=1800
- TZ=Australia/Perth
volumes:
- lidarr_config:/config
- beets_config:/beets
- ./install_beets.bash:/custom-cont-init.d/install_beets.bash:ro
- /media:/media
restart: unless-stopped
labels:
caddy: lidarr.ferngarden.net
caddy.1_import: internal
caddy.2_import: authentik
readarr-audiobooks:
image: lscr.io/linuxserver/readarr:develop
container_name: readarr-audiobooks
networks:
- default
- media
- proxy
environment:
- PUID=1000
- PGID=1800
- TZ=Australia/Perth
volumes:
- readarr-audiobooks_config:/config
- /media:/media
restart: unless-stopped
labels:
caddy: readarr-audiobooks.ferngarden.net
caddy.1_import: internal
caddy.2_import: authentik
readarr-ebooks:
image: lscr.io/linuxserver/readarr:develop
container_name: readarr-ebooks
networks:
- default
- media
- proxy
environment:
- PUID=1000
- PGID=1800
- TZ=Australia/Perth
volumes:
- readarr-ebooks_config:/config
- /media:/media
restart: unless-stopped
labels:
caddy: readarr-ebooks.ferngarden.net
caddy.1_import: internal
caddy.2_import: authentik
letterboxd-list-radarr:
image: screeny05/letterboxd-list-radarr:latest
container_name: letterboxd-list-radarr
restart: unless-stopped
networks:
- default
environment:
- REDIS_URL=redis://letterboxd-list-radarr_redis:6379
depends_on:
- letterboxd-list-radarr_redis
letterboxd-list-radarr_redis:
container_name: letterboxd-list-radarr_redis
restart: unless-stopped
networks:
- default
volumes:
- letterboxd-list-radarr_redis:/data
image: redis:6.0
soularr:
image: mrusse08/soularr:latest
container_name: soularr
networks:
- default
- media
user: 1000:1800
environment:
- TZ=Australia/Perth
- SCRIPT_INTERVAL=300
volumes:
- /media:/media
- /mnt/docker/soularr/config:/data
restart: unless-stopped
cleanuperr:
image: ghcr.io/flmorg/cleanuperr:latest
container_name: cleanuperr
restart: unless-stopped
networks:
- default
- media
volumes:
- cleanuperr_logs:/var/logs
- /media:/media
environment:
- TZ=Australia/Perth
- DOWNLOADCLEANER__ENABLED=true
- DOWNLOADCLEANER__UNLINKED_TARGET_CATEGORY=unlinked
- DOWNLOADCLEANER__UNLINKED_USE_TAG=true
- DOWNLOADCLEANER__UNLINKED_CATEGORIES__0=tv
- DOWNLOADCLEANER__UNLINKED_CATEGORIES__1=film
- DOWNLOAD_CLIENT=qBittorrent
- QBITTORRENT__URL=http://qbittorrent_gluetun:8080
- QBITTORRENT__USERNAME=fern
- QBITTORRENT__PASSWORD=${QBITTORRENT__PASSWORD}
profilarr:
image: santiagosayshey/profilarr:latest
container_name: profilarr
networks:
- default
- media
- proxy
volumes:
- profilarr_config:/config
environment:
- TZ=Australia/Perth
restart: unless-stopped
labels:
caddy: profilarr.ferngarden.net
caddy.import: internal
caddy.reverse_proxy: "{{upstreams 6868}}"
networks:
default:
proxy:
external: true
media:
name: media
volumes:
bazarr_config:
name: bazarr_config
beets_config:
name: beets_config
cleanuperr_config:
name: cleanuperr_config
cleanuperr_logs:
name: cleanuperr_logs
jackett_config:
name: jackett_config
jackett_downloads:
name: jackett_downloads
jellyseerr_config:
name: jellyseerr_config
letterboxd-list-radarr_redis:
name: letterboxd-list-radarr_redis
lidarr_config:
name: lidarr_config
profilarr_config:
name: profilarr_config
prowlarr_config:
name: prowlarr_config
radarr_config:
name: radarr_config
readarr-audiobooks_config:
name: readarr-audiobooks_config
readarr-ebooks_config:
name: readarr-ebooks_config
sonarr_config:
name: sonarr_config

4
arr/install_beets.bash Normal file
View file

@ -0,0 +1,4 @@
#!/bin/bash
echo "**** installing beets ****"
apk add --no-cache beets py3-pylast py3-pyacoustid py3-beautifulsoup4 py3-langdetect ffmpeg

1
audiobookshelf/README.md Normal file
View file

@ -0,0 +1 @@
# Compose file for Audiobookshelf

View file

@ -0,0 +1,28 @@
services:
audiobookshelf:
image: ghcr.io/advplyr/audiobookshelf:latest
container_name: audiobookshelf
restart: unless-stopped
networks:
- default
- proxy
volumes:
- audiobookshelf_config:/config
- audiobookshelf_metadata:/metadata
- /media:/media
environment:
- TZ=Australia/Perth
labels:
caddy: audiobooks.fern.garden
caddy.reverse_proxy: "{{upstreams 80}}"
networks:
default:
proxy:
external: true
volumes:
audiobookshelf_config:
name: audiobookshelf_config
audiobookshelf_metadata:
name: audiobookshelf_metadata

7
authentik/README.md Normal file
View file

@ -0,0 +1,7 @@
# Compose file for Authentik
## Environment Variables
- POSTGRES_PASSWORD - database password
- AUTHENTIK_SECRET_KEY - Key used for cookie signing
- AUTHENTIK_EMAIL__PASSWORD - SMTP password
- AUTHENTIK_LDAP_TOKEN - token for LDAP outpost
- AUTHENTIK_PROXY_TOKEN - token for proxy outpost

143
authentik/compose.yaml Normal file
View file

@ -0,0 +1,143 @@
services:
authentik_db:
image: docker.io/library/postgres:16-alpine
container_name: authentik_db
networks:
- default
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
start_period: 20s
interval: 30s
retries: 5
timeout: 5s
volumes:
- authentik_db:/var/lib/postgresql/data
environment:
- POSTGRES_USER=authentik
- POSTGRES_DB=authentik
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
authentik_redis:
image: docker.io/library/redis:alpine
container_name: authentik_redis
networks:
- default
command: --save 60 1 --loglevel warning
restart: always
healthcheck:
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
start_period: 20s
interval: 30s
retries: 5
timeout: 3s
volumes:
- authentik_redis:/data
authentik:
image: ghcr.io/goauthentik/server:${AUTHENTIK_VERSION}
container_name: authentik
networks:
- default
- proxy
restart: unless-stopped
command: server
environment:
- AUTHENTIK_SECRET_KEY=${AUTHENTIK_SECRET_KEY}
- AUTHENTIK_REDIS__HOST=authentik_redis
- AUTHENTIK_POSTGRESQL__HOST=authentik_db
- AUTHENTIK_POSTGRESQL__USER=authentik
- AUTHENTIK_POSTGRESQL__NAME=authentik
- AUTHENTIK_POSTGRESQL__PASSWORD=${POSTGRES_PASSWORD}
- AUTHENTIK_OUTPOSTS__DISABLE_EMBEDDED_OUTPOST=true
volumes:
- authentik_media:/media
- authentik_templates:/templates
depends_on:
authentik_db:
condition: service_healthy
authentik_redis:
condition: service_healthy
labels:
caddy: auth.fern.garden
caddy.reverse_proxy: "{{upstreams 9000}}"
authentik_worker:
image: ghcr.io/goauthentik/server:${AUTHENTIK_VERSION}
container_name: authentik_worker
networks:
- default
restart: unless-stopped
command: worker
environment:
- AUTHENTIK_SECRET_KEY=${AUTHENTIK_SECRET_KEY}
- AUTHENTIK_REDIS__HOST=authentik_redis
- AUTHENTIK_POSTGRESQL__HOST=authentik_db
- AUTHENTIK_POSTGRESQL__USER=authentik
- AUTHENTIK_POSTGRESQL__NAME=authentik
- AUTHENTIK_POSTGRESQL__PASSWORD=${POSTGRES_PASSWORD}
- AUTHENTIK_OUTPOSTS__DISABLE_EMBEDDED_OUTPOST=true
user: root
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- authentik_media:/media
- authentik_templates:/templates
- authentik_certs:/certs
depends_on:
authentik_db:
condition: service_healthy
authentik_redis:
condition: service_healthy
authentik_proxy:
image: ghcr.io/goauthentik/proxy:${AUTHENTIK_VERSION}
container_name: authentik_proxy
networks:
- default
- proxy
environment:
- AUTHENTIK_HOST=http://authentik:9000
- AUTHENTIK_HOST_BROWSER=https://auth.fern.garden
- AUTHENTIK_INSECURE=true
- AUTHENTIK_TOKEN=${AUTHENTIK_PROXY_TOKEN}
depends_on:
authentik:
condition: service_healthy
authentik_worker:
condition: service_healthy
authentik_ldap:
image: ghcr.io/goauthentik/ldap:${AUTHENTIK_VERSION}
container_name: authentik_ldap
networks:
- default
ports:
- 389:3389
- 636:6636
environment:
- AUTHENTIK_HOST=http://authentik:9000
- AUTHENTIK_HOST_BROWSER=https://auth.fern.garden
- AUTHENTIK_INSECURE=true
- AUTHENTIK_TOKEN=${AUTHENTIK_LDAP_TOKEN}
depends_on:
authentik:
condition: service_healthy
authentik_worker:
condition: service_healthy
volumes:
authentik_db:
name: authentik_db
authentik_redis:
name: authentik_redis
authentik_media:
name: authentik_media
authentik_certs:
name: authentik_certs
authentik_templates:
name: authentik_templates
networks:
default:
proxy:
external: true

106
caddy/Caddyfile Normal file
View file

@ -0,0 +1,106 @@
## Global Options ##
{
acme_dns cloudflare {env.CF_API_TOKEN}
auto_https prefer_wildcard
email mail@fern.garden
}
## Snippets ##
(internal) {
@denied not remote_ip private_ranges
abort @denied
}
(authentik) {
reverse_proxy authentik_proxy:9000
}
## Root Hosts ##
*.fern.garden {
redir https://fern.garden
}
*.ferngarden.net {
import internal
redir https://ferngarden.net
}
*.transgender.pet {
redir https://transgender.pet
}
fern.garden {
route {
reverse_proxy /.well-known/matrix/* https://matrix.fern.garden {
header_up Host {upstream_hostport}
}
root * /srv/fern.garden
file_server
}
}
ferngarden.net {
import internal
respond / "nothing here :(" 404
}
transgender.pet {
file_server
root * /srv/transgender.pet
}
## Proxmox ##
spoonbill.ferngarden.net {
import internal
reverse_proxy 10.0.1.2:8006 {
transport http {
tls_insecure_skip_verify
}
}
}
egret.ferngarden.net {
import internal
reverse_proxy 10.0.1.3:8006 {
transport http {
tls_insecure_skip_verify
}
}
}
pdm.ferngarden.net {
import internal
reverse_proxy 10.0.1.120:8443 {
transport http {
tls_insecure_skip_verify
}
}
}
pbs.ferngarden.net {
import internal
reverse_proxy 10.0.1.121:8007 {
transport http {
tls_insecure_skip_verify
}
}
}
## VMs/Containers ##
dns.ferngarden.net {
import internal
reverse_proxy 10.0.1.111:5380
}
ffsync.fern.garden {
reverse_proxy 10.0.1.102:8000
}
home.fern.garden {
reverse_proxy 10.0.1.103:8123
}

16
caddy/Dockerfile Normal file
View file

@ -0,0 +1,16 @@
ARG CADDY_VERSION=2.10.0
FROM caddy:${CADDY_VERSION}-builder AS builder
RUN xcaddy build \
--with github.com/lucaslorentz/caddy-docker-proxy/v2 \
--with github.com/caddy-dns/cloudflare \
--with github.com/caddyserver/caddy/v2/modules/standard \
--with github.com/hslatman/caddy-crowdsec-bouncer/http \
--with github.com/hslatman/caddy-crowdsec-bouncer/layer4 \
--with github.com/hslatman/caddy-crowdsec-bouncer/appsec
FROM caddy:${CADDY_VERSION}-alpine
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
CMD ["caddy", "docker-proxy"]

3
caddy/README.md Normal file
View file

@ -0,0 +1,3 @@
# Compose file for caddy
## Environment Variables
- CF_API_TOKEN - token for CloudFlare DNS challenge

34
caddy/compose.yaml Normal file
View file

@ -0,0 +1,34 @@
services:
caddy:
image: git.fern.garden/fern/caddy:latest
container_name: caddy
restart: unless-stopped
ports:
- 80:80
- 443:443
- 443:443/udp
networks:
- default
- proxy
- traefik
environment:
- CADDY_INGRESS_NETWORKS=proxy
- CF_API_TOKEN=${CF_API_TOKEN}
- CROWDSEC_API_KEY=${CROWDSEC_API_KEY}
- CADDY_DOCKER_CADDYFILE_PATH=/etc/caddy/Caddyfile
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./Caddyfile:/etc/caddy/Caddyfile
- /srv:/srv
- caddy_data:/data
volumes:
caddy_data:
name: caddy_data
networks:
default:
proxy:
external: true
traefik:
external: true

1
calibre/README.md Normal file
View file

@ -0,0 +1 @@
# Compose file for calibre & calibre-web

53
calibre/compose.yaml Normal file
View file

@ -0,0 +1,53 @@
services:
calibre:
image: lscr.io/linuxserver/calibre:latest
container_name: calibre
networks:
- default
- proxy
- media
security_opt:
- seccomp:unconfined
environment:
- PUID=1000
- PGID=1800
- TZ=Australia/Perth
volumes:
- calibre_config:/config
- /media:/media
restart: unless-stopped
labels:
caddy: calibre.ferngarden.net
caddy.import: internal
caddy.reverse_proxy: "{{upstreams 8080}}"
calibre-web:
image: lscr.io/linuxserver/calibre-web:latest
container_name: calibre-web
networks:
- default
- proxy
environment:
- PUID=1000
- PGID=1800
- TZ=Australia/Perth
volumes:
- calibre-web_config:/config
- /media:/media
restart: unless-stopped
labels:
caddy: books.fern.garden
caddy.reverse_proxy: "{{upstreams 8083}}"
networks:
default:
proxy:
external: true
media:
external: true
volumes:
calibre_config:
name: calibre_config
calibre-web_config:
name: calibre-web_config

21
dozzle/compose.yaml Normal file
View file

@ -0,0 +1,21 @@
services:
dozzle:
image: amir20/dozzle:latest
container_name: dozzle
networks:
- default
- metrics
- proxy
labels:
caddy: dozzle.ferngarden.net
caddy.import: internal
caddy.reverse_proxy: '{{ upstreams 8080 }}'
environment:
DOZZLE_REMOTE_HOST: tcp://docker_socket_proxy:2375|docker.local,tcp://10.0.1.105:2375|minecraft.local,tcp://10.0.1.4:2375|weebill.local
networks:
default:
metrics:
external: true
proxy:
external: true

3
forgejo/README.md Normal file
View file

@ -0,0 +1,3 @@
# Compose file for Forgejo
## Environment Variables
- POSTGRES_PASSWORD - database password

51
forgejo/compose.yaml Normal file
View file

@ -0,0 +1,51 @@
services:
server:
image: codeberg.org/forgejo/forgejo:11
container_name: forgejo
networks:
- proxy
- default
ports:
- 222:22
environment:
- USER_UID=1000
- USER_GID=1000
- FORGEJO__database__DB_TYPE=postgres
- FORGEJO__database__HOST=forgejo_db:5432
- FORGEJO__database__NAME=forgejo
- FORGEJO__database__USER=forgejo
- FORGEJO__database__PASSWD=${POSTGRES_PASSWORD}
restart: unless-stopped
volumes:
- forgejo_data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
depends_on:
- forgejo_db
labels:
caddy: git.fern.garden
caddy.reverse_proxy: "{{upstreams 3000}}"
forgejo_db:
image: postgres:14
container_name: forgejo_db
networks:
- default
restart: unless-stopped
environment:
- POSTGRES_USER=forgejo
- POSTGRES_DB=forgejo
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
volumes:
- forgejo_db:/var/lib/postgresql/data
networks:
default:
proxy:
external: true
volumes:
forgejo_data:
name: forgejo_data
forgejo_db:
name: forgejo_db

19
glance/compose.yaml Normal file
View file

@ -0,0 +1,19 @@
services:
glance:
container_name: glance
image: glanceapp/glance
restart: unless-stopped
volumes:
- /mnt/docker/glance/config:/app/config
networks:
- default
- proxy
labels:
caddy: glance.ferngarden.net
caddy.import: internal
caddy.reverse_proxy: '{{ upstreams 8080 }}'
networks:
default:
proxy:
external: true

1
grocy/README.md Normal file
View file

@ -0,0 +1 @@
# Compose file for grocy

33
grocy/compose.yaml Normal file
View file

@ -0,0 +1,33 @@
services:
grocy:
image: lscr.io/linuxserver/grocy:latest
container_name: grocy
environment:
- PUID=1000
- PGID=1000
- TZ=Australia/Perth
- GROCY_FEATURE_FLAG_RECIPES=false
- GROCY_FEATURE_FLAG_SHOPPINGLIST=false
- GROCY_FEATURE_FLAG_STOCK=false
- GROCY_CURRENCY=AUD
networks:
- default
- proxy
ports:
- 9192:80
volumes:
- grocy_config:/config
restart: unless-stopped
labels:
caddy: grocy.ferngarden.net
caddy.import: internal
caddy.reverse_proxy: "{{upstreams 80}}"
networks:
default:
proxy:
external: true
volumes:
grocy_config:
name: grocy_config

4
homebox/README.md Normal file
View file

@ -0,0 +1,4 @@
# Compose file for [template]
## Services
## Environment Variables
- EXAMPLE_VAR - Description

28
homebox/compose.yaml Normal file
View file

@ -0,0 +1,28 @@
services:
homebox:
image: ghcr.io/sysadminsmedia/homebox:latest-rootless
container_name: homebox
restart: unless-stopped
environment:
- HBOX_LOG_LEVEL=info
- HBOX_LOG_FORMAT=text
- HBOX_WEB_MAX_FILE_UPLOAD=10
- HBOX_OPTIONS_ALLOW_ANALYTICS=false
volumes:
- homebox_data:/data/
networks:
- default
- proxy
labels:
caddy: homebox.ferngarden.net
caddy.import: internal
caddy.reverse_proxy: '{{ upstreams 7745 }}'
networks:
default:
proxy:
external: true
volumes:
homebox_data:
name: homebox_data

24
homepage/compose.yaml Normal file
View file

@ -0,0 +1,24 @@
services:
homepage:
image: ghcr.io/gethomepage/homepage:latest
container_name: homepage
volumes:
- /mnt/docker/homepage/config:/app/config
user: 1000:1000
restart: unless-stopped
environment:
HOMEPAGE_ALLOWED_HOSTS: dash.ferngarden.net
networks:
- default
- proxy
- metrics
labels:
caddy: dash.ferngarden.net
caddy.import: internal
caddy.reverse_proxy: '{{ upstreams 3000 }}'
networks:
proxy:
external: true
metrics:
external: true

5
hortusfox/README.md Normal file
View file

@ -0,0 +1,5 @@
# Compose file for [template]
## Environment Variables
- APP_ADMIN_PASSWORD - login password
- MYSQL_PASSWORD - database password
- MYSQL_ROOT_PASSWORD - database root password

57
hortusfox/compose.yaml Normal file
View file

@ -0,0 +1,57 @@
services:
hortusfox:
image: ghcr.io/danielbrendel/hortusfox-web:latest
container_name: hortusfox
volumes:
- hortusfox_images:/var/www/html/public/img
- hortusfox_logs:/var/www/html/hortusfox/logs
- hortusfox_backup:/var/www/html/public/backup
- hortusfox_themes:/var/www/html/public/themes
- hortusfox_migrate:/var/www/html/hortusfox/migrations
environment:
APP_ADMIN_EMAIL: mail@fern.garden
APP_ADMIN_PASSWORD: ${APP_ADMIN_PASSWORD}
APP_TIMEZONE: Australia/Perth
DB_HOST: hortusfox_db
DB_PORT: 3306
DB_DATABASE: hortusfox
DB_USERNAME: hortusfox
DB_PASSWORD: ${MYSQL_PASSWORD}
DB_CHARSET: "utf8mb4"
networks:
- default
- proxy
depends_on:
- hortusfox_db
labels:
caddy: hortusfox.ferngarden.net
caddy.import: internal
caddy.reverse_proxy: "{{upstreams 80}}"
hortusfox_db:
image: mariadb
container_name: hortusfox_db
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: hortusfox
MYSQL_USER: hortusfox
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
volumes:
- hortusfox_db:/var/lib/mysql
networks:
- default
networks:
default:
proxy:
external: true
volumes:
hortusfox_db:
hortusfox_images:
hortusfox_logs:
hortusfox_backup:
hortusfox_themes:
hortusfox_migrate:

3
immich/README.md Normal file
View file

@ -0,0 +1,3 @@
# Compose file for Immich
## Environment Variables
- DB_PASSWORD - database password

78
immich/compose.yaml Normal file
View file

@ -0,0 +1,78 @@
services:
immich:
container_name: immich
hostname: immich-server
image: ghcr.io/immich-app/immich-server:release
volumes:
- immich_library:/usr/src/app/upload
- /etc/localtime:/etc/localtime:ro
networks:
- default
- proxy
environment:
- DB_USERNAME=postgres
- DB_DATABASE_NAME=immich
- DB_PASSWORD=${DB_PASSWORD}
devices:
- /dev/dri:/dev/dri
depends_on:
- immich_redis
- immich_db
restart: unless-stopped
healthcheck:
disable: false
labels:
caddy: photos.ferngarden.net
caddy.import: internal
caddy.reverse_proxy: "{{upstreams 2283}}"
immich_ml:
container_name: immich_ml
hostname: immich-machine-learning
image: ghcr.io/immich-app/immich-machine-learning:release
volumes:
- immich_ml_cache:/cache
networks:
- default
restart: unless-stopped
healthcheck:
disable: false
immich_redis:
container_name: immich_redis
hostname: redis
image: docker.io/valkey/valkey:8-bookworm@sha256:ff21bc0f8194dc9c105b769aeabf9585fea6a8ed649c0781caeac5cb3c247884
networks:
- default
healthcheck:
test: redis-cli ping || exit 1
restart: unless-stopped
immich_db:
container_name: immich_db
hostname: database
image: ghcr.io/immich-app/postgres:14-vectorchord0.3.0-pgvectors0.2.0@sha256:fa4f6e0971f454cd95fec5a9aaed2ed93d8f46725cc6bc61e0698e97dba96da1
networks:
- default
environment:
- POSTGRES_PASSWORD=${DB_PASSWORD}
- POSTGRES_USER=postgres
- POSTGRES_DB=immich
- POSTGRES_INITDB_ARGS='--data-checksums'
volumes:
- immich_db:/var/lib/postgresql/data
restart: always
networks:
default:
proxy:
external: true
volumes:
immich_library:
name: immich_library
immich_ml_cache:
name: immich_ml_cache
immich_db:
name: immich_db

17
it-tools/compose.yaml Normal file
View file

@ -0,0 +1,17 @@
services:
it-tools:
image: corentinth/it-tools:latest
container_name: it-tools
restart: unless-stopped
networks:
- default
- proxy
labels:
caddy: it-tools.ferngarden.net
caddy.import: internal
caddy.reverse_proxy: '{{ upstreams 80 }}'
networks:
default:
proxy:
external: true

1
jellyfin/README.md Normal file
View file

@ -0,0 +1 @@
# Compose file for Jellyfin

100
jellyfin/compose.yaml Normal file
View file

@ -0,0 +1,100 @@
services:
jellyfin:
image: jellyfin/jellyfin
container_name: jellyfin
user: 1000:1800
group_add:
- 992
devices:
- /dev/dri/renderD128:/dev/dri/renderD128
networks:
- default
- proxy
- media
volumes:
- jellyfin_cache:/var/cache/jellyfin
- jellyfin_config:/etc/jellyfin
- jellyfin_data:/var/lib/jellyfin
- jellyfin_logs:/var/log/jellyfin
- /media:/media
restart: unless-stopped
ports:
- 8096:8096
environment:
- JELLYFIN_PublishedServerUrl=https://jellyfin.fern.garden
- JELLYFIN_CACHE_DIR=/var/cache/jellyfin
- JELLYFIN_CONFIG_DIR=/etc/jellyfin
- JELLYFIN_DATA_DIR=/var/lib/jellyfin
- JELLYFIN_LOG_DIR=/var/log/jellyfin
- TZ=Australia/Perth
labels:
caddy: jellyfin.fern.garden
caddy.@blacklist.not.path: "/metrics"
caddy.reverse_proxy: "@blacklist {{upstreams 8096}}"
jellystat_db:
image: postgres:15.2
shm_size: '1gb'
container_name: jellystat_db
restart: unless-stopped
logging:
driver: "json-file"
options:
max-file: "5"
max-size: "10m"
environment:
POSTGRES_USER: jellystat
POSTGRES_PASSWORD: ${JELLYSTAT_POSTGRES_PASSWORD}
networks:
- default
volumes:
- jellystat_db:/var/lib/postgresql/data
jellystat:
image: cyfershepard/jellystat:latest
container_name: jellystat
restart: unless-stopped
logging:
driver: "json-file"
options:
max-file: "5"
max-size: "10m"
environment:
POSTGRES_USER: jellystat
POSTGRES_PASSWORD: ${JELLYSTAT_POSTGRES_PASSWORD}
POSTGRES_IP: jellystat_db
POSTGRES_PORT: 5432
JWT_SECRET: ${JELLYSTAT_JWT_SECRET}
TZ: Australia/Perth
volumes:
- jellystat_data:/app/backend/backup-data
networks:
- default
- proxy
depends_on:
- jellystat_db
labels:
caddy: jellystat.ferngarden.net
caddy.import: internal
caddy.reverse_proxy: '{{upstreams 3000}}'
networks:
default:
media:
external: true
proxy:
external: true
volumes:
jellyfin_config:
name: jellyfin_config
jellyfin_cache:
name: jellyfin_cache
jellyfin_data:
name: jellyfin_data
jellyfin_logs:
name: jellyfin_logs
jellystat_db:
name: jellystat_db
jellystat_data:
name: jellystat_data

4
komga/README.md Normal file
View file

@ -0,0 +1,4 @@
# Compose file for [template]
## Services
## Environment Variables
- EXAMPLE_VAR - Description

30
komga/compose.yaml Normal file
View file

@ -0,0 +1,30 @@
services:
komga:
image: gotson/komga
container_name: komga
volumes:
- komga_config:/config
- /media:/media:ro
user: "1000:1800"
environment:
- TZ=Australia/Perth
- KOMGA_OAUTH2_ACCOUNT_CREATION=true
restart: unless-stopped
networks:
- default
- media
- proxy
labels:
caddy: comics.fern.garden
caddy.reverse_proxy: '{{upstreams 25600}}'
networks:
default:
media:
external: true
proxy:
external: true
volumes:
komga_config:
name: komga_config

4
mailserver/README.md Normal file
View file

@ -0,0 +1,4 @@
# Compose file for [template]
## Services
## Environment Variables
- EXAMPLE_VAR - Description

41
mailserver/compose.yaml Normal file
View file

@ -0,0 +1,41 @@
services:
mailserver:
image: ghcr.io/docker-mailserver/docker-mailserver:latest
container_name: mailserver
hostname: mail.ferngarden.net
env_file: mailserver.env
environment:
SSL_TYPE: manual
SSL_CERT_PATH: /srv/tls/caddy/certificates/acme-v02.api.letsencrypt.org-directory/wildcard_.ferngarden.net/wildcard_.ferngarden.net.crt
SSL_KEY_PATH: /srv/tls/caddy/certificates/acme-v02.api.letsencrypt.org-directory/wildcard_.ferngarden.net/wildcard_.ferngarden.net.key
ports:
- "25:25" # SMTP (explicit TLS => STARTTLS, Authentication is DISABLED => use port 465/587 instead)
- "143:143" # IMAP4 (explicit TLS => STARTTLS)
- "465:465" # ESMTP (implicit TLS)
- "587:587" # ESMTP (explicit TLS => STARTTLS)
- "993:993" # IMAP4 (implicit TLS)
volumes:
- mailserver_data:/var/mail/
- mailserver_state:/var/mail-state/
- mailserver_logs:/var/log/mail/
- mailserver_config:/tmp/docker-mailserver/
- /etc/localtime:/etc/localtime:ro
- caddy_data:/srv/tls
restart: always
stop_grace_period: 1m
healthcheck:
test: "ss --listening --ipv4 --tcp | grep --silent ':smtp' || exit 1"
timeout: 3s
retries: 0
volumes:
mailserver_data:
name: mailserver_data
mailserver_state:
name: mailserver_state
mailserver_logs:
name: mailserver_logs
mailserver_config:
name: mailserver_config
caddy_data:
external: true

660
mailserver/mailserver.env Normal file
View file

@ -0,0 +1,660 @@
# -----------------------------------------------
# --- Mailserver Environment Variables ----------
# -----------------------------------------------
# DOCUMENTATION FOR THESE VARIABLES IS FOUND UNDER
# https://docker-mailserver.github.io/docker-mailserver/latest/config/environment/
# -----------------------------------------------
# --- General Section ---------------------------
# -----------------------------------------------
# **empty** => Internally uses the `hostname --fqdn` command to get the canonical hostname assigned to the DMS container.
# => Specify an FQDN (fully-qualified domain name) to serve mail for. The hostname is required for DMS to function correctly
#
# **WARNING**: Setting OVERRIDE_HOSTNAME can have difficult to predict side effects:
# https://docker-mailserver.github.io/docker-mailserver/latest/config/environment/#override_hostname
OVERRIDE_HOSTNAME=
# Set the log level for DMS.
# This is mostly relevant for container startup scripts and change detection event feedback.
#
# Valid values (in order of increasing verbosity) are: `error`, `warn`, `info`, `debug` and `trace`.
# The default log level is `info`.
LOG_LEVEL=info
# critical => Only show critical messages
# error => Only show erroneous output
# **warn** => Show warnings
# info => Normal informational output
# debug => Also show debug messages
SUPERVISOR_LOGLEVEL=
# Support for deployment where these defaults are not compatible (eg: some NAS appliances):
# /var/mail vmail User ID (default: 5000)
DMS_VMAIL_UID=
# /var/mail vmail Group ID (default: 5000)
DMS_VMAIL_GID=
# **empty** => use FILE
# LDAP => use LDAP authentication
# OIDC => use OIDC authentication (not yet implemented)
# FILE => use local files (this is used as the default)
ACCOUNT_PROVISIONER=
# empty => postmaster@domain.com
# => Specify the postmaster address
POSTMASTER_ADDRESS=
# Check for updates on container start and then once a day
# If an update is available, a mail is sent to POSTMASTER_ADDRESS
# 0 => Update check disabled
# 1 => Update check enabled
ENABLE_UPDATE_CHECK=1
# Customize the update check interval.
# Number + Suffix. Suffix must be 's' for seconds, 'm' for minutes, 'h' for hours or 'd' for days.
UPDATE_CHECK_INTERVAL=1d
# Set different options for mynetworks option (can be overwrite in postfix-main.cf)
# **WARNING**: Adding the docker network's gateway to the list of trusted hosts, e.g. using the `network` or
# `connected-networks` option, can create an open relay
# https://github.com/docker-mailserver/docker-mailserver/issues/1405#issuecomment-590106498
# The same can happen for rootless podman. To prevent this, set the value to "none" or configure slirp4netns
# https://github.com/docker-mailserver/docker-mailserver/issues/2377
#
# none => Explicitly force authentication
# container => Container IP address only
# host => Add docker container network (ipv4 only)
# network => Add all docker container networks (ipv4 only)
# connected-networks => Add all connected docker networks (ipv4 only)
PERMIT_DOCKER=none
# Set the timezone. If this variable is unset, the container runtime will try to detect the time using
# `/etc/localtime`, which you can alternatively mount into the container. The value of this variable
# must follow the pattern `AREA/ZONE`, i.e. of you want to use Germany's time zone, use `Europe/Berlin`.
# You can lookup all available timezones here: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
TZ=Australia/Perth
# In case you network interface differs from 'eth0', e.g. when you are using HostNetworking in Kubernetes,
# you can set NETWORK_INTERFACE to whatever interface you want. This interface will then be used.
# - **empty** => eth0
NETWORK_INTERFACE=
# empty => modern
# modern => Limits the cipher suite to secure ciphers only.
# intermediate => Relaxes security by adding additional ciphers for broader compatibility.
# NOTE: The minimum TLS version supported is 1.2, if you need to lower that follow this workaround advice:
# https://github.com/docker-mailserver/docker-mailserver/pull/2945#issuecomment-1949907964
TLS_LEVEL=
# Configures the handling of creating mails with forged sender addresses.
#
# **0** => (not recommended) Mail address spoofing allowed. Any logged in user may create email messages with a forged sender address (see also https://en.wikipedia.org/wiki/Email_spoofing).
# 1 => Mail spoofing denied. Each user may only send with their own or their alias addresses. Addresses with extension delimiters(http://www.postfix.org/postconf.5.html#recipient_delimiter) are not able to send messages.
SPOOF_PROTECTION=
# Enables the Sender Rewriting Scheme. SRS is needed if your mail server acts as forwarder. See [postsrsd](https://github.com/roehling/postsrsd/blob/main/README.rst) for further explanation.
# - **0** => Disabled
# - 1 => Enabled
ENABLE_SRS=0
# Enables the OpenDKIM service.
# **1** => Enabled
# 0 => Disabled
ENABLE_OPENDKIM=1
# Enables the OpenDMARC service.
# **1** => Enabled
# 0 => Disabled
ENABLE_OPENDMARC=1
# Enabled `policyd-spf` in Postfix's configuration. You will likely want to set this
# to `0` in case you're using Rspamd (`ENABLE_RSPAMD=1`).
#
# - 0 => Disabled
# - **1** => Enabled
ENABLE_POLICYD_SPF=1
# Enables POP3 service
# - **0** => Disabled
# - 1 => Enabled
ENABLE_POP3=
# Enables IMAP service
# - 0 => Disabled
# - **1** => Enabled
ENABLE_IMAP=1
# Enables ClamAV, and anti-virus scanner.
# 1 => Enabled
# **0** => Disabled
ENABLE_CLAMAV=0
# Add the value of this ENV as a prefix to the mail subject when spam is detected.
# NOTE: This subject prefix may be redundant (by default spam is delivered to a junk folder).
# It provides value when your junk mail is stored alongside legitimate mail instead of a separate location (like with `SPAMASSASSIN_SPAM_TO_INBOX=1` or `MOVE_SPAM_TO_JUNK=0` or a POP3 only setup, without IMAP).
# NOTE: When not using Docker Compose, other CRI may not support quote-wrapping the value here to preserve any trailing white-space.
SPAM_SUBJECT=
# Enables Rspamd
# **0** => Disabled
# 1 => Enabled
ENABLE_RSPAMD=0
# When `ENABLE_RSPAMD=1`, an internal Redis instance is enabled implicitly.
# This setting provides an opt-out to allow using an external instance instead.
# 0 => Disabled
# 1 => Enabled
ENABLE_RSPAMD_REDIS=
# When enabled,
#
# 1. the "[autolearning][rspamd-autolearn]" feature is turned on;
# 2. the Bayes classifier will be trained when moving mails from or to the Junk folder (with the help of Sieve scripts).
#
# **0** => disabled
# 1 => enabled
RSPAMD_LEARN=0
# This settings controls whether checks should be performed on emails coming
# from authenticated users (i.e. most likely outgoing emails). The default value
# is `0` in order to align better with SpamAssassin. We recommend reading
# through https://rspamd.com/doc/tutorials/scanning_outbound.html though to
# decide for yourself whether you need and want this feature.
#
# Note that DKIM signing of e-mails will still happen.
RSPAMD_CHECK_AUTHENTICATED=0
# Controls whether the Rspamd Greylisting module is enabled.
# This module can further assist in avoiding spam emails by greylisting
# e-mails with a certain spam score.
#
# **0** => disabled
# 1 => enabled
RSPAMD_GREYLISTING=0
# Can be used to enable or disable the Hfilter group module.
#
# - 0 => Disabled
# - **1** => Enabled
RSPAMD_HFILTER=1
# Can be used to control the score when the HFILTER_HOSTNAME_UNKNOWN symbol applies. A higher score is more punishing. Setting it to 15 is equivalent to rejecting the email when the check fails.
#
# Default: 6
RSPAMD_HFILTER_HOSTNAME_UNKNOWN_SCORE=6
# Can be used to enable or disable the (still experimental) neural module.
#
# - **0** => Disabled
# - 1 => Enabled
RSPAMD_NEURAL=0
# Amavis content filter (used for ClamAV & SpamAssassin)
# 0 => Disabled
# 1 => Enabled
ENABLE_AMAVIS=1
# -1/-2/-3 => Only show errors
# **0** => Show warnings
# 1/2 => Show default informational output
# 3/4/5 => log debug information (very verbose)
AMAVIS_LOGLEVEL=0
# This enables DNS block lists in Postscreen.
# Note: Emails will be rejected, if they don't pass the block list checks!
# **0** => DNS block lists are disabled
# 1 => DNS block lists are enabled
ENABLE_DNSBL=0
# If you enable Fail2Ban, don't forget to add the following lines to your `compose.yaml`:
# cap_add:
# - NET_ADMIN
# Otherwise, `nftables` won't be able to ban IPs.
ENABLE_FAIL2BAN=0
# Fail2Ban blocktype
# drop => drop packet (send NO reply)
# reject => reject packet (send ICMP unreachable)
FAIL2BAN_BLOCKTYPE=drop
# 1 => Enables Managesieve on port 4190
# empty => disables Managesieve
ENABLE_MANAGESIEVE=
# **enforce** => Allow other tests to complete. Reject attempts to deliver mail with a 550 SMTP reply, and log the helo/sender/recipient information. Repeat this test the next time the client connects.
# drop => Drop the connection immediately with a 521 SMTP reply. Repeat this test the next time the client connects.
# ignore => Ignore the failure of this test. Allow other tests to complete. Repeat this test the next time the client connects. This option is useful for testing and collecting statistics without blocking mail.
POSTSCREEN_ACTION=enforce
# empty => all daemons start
# 1 => only launch postfix smtp
SMTP_ONLY=
# Please read [the SSL page in the documentation](https://docker-mailserver.github.io/docker-mailserver/latest/config/security/ssl) for more information.
#
# empty => SSL disabled
# letsencrypt => Enables Let's Encrypt certificates
# custom => Enables custom certificates
# manual => Let's you manually specify locations of your SSL certificates for non-standard cases
# self-signed => Enables self-signed certificates
SSL_TYPE=
# These are only supported with `SSL_TYPE=manual`.
# Provide the path to your cert and key files that you've mounted access to within the container.
SSL_CERT_PATH=
SSL_KEY_PATH=
# Optional: A 2nd certificate can be supported as fallback (dual cert support), eg ECDSA with an RSA fallback.
# Useful for additional compatibility with older MTA and MUA (eg pre-2015).
SSL_ALT_CERT_PATH=
SSL_ALT_KEY_PATH=
# Set how many days a virusmail will stay on the server before being deleted
# empty => 7 days
VIRUSMAILS_DELETE_DELAY=
# Configure Postfix `virtual_transport` to deliver mail to a different LMTP client (default is a dovecot socket).
# Provide any valid URI. Examples:
#
# empty => `lmtp:unix:/var/run/dovecot/lmtp` (default, configured in Postfix main.cf)
# `lmtp:unix:private/dovecot-lmtp` (use socket)
# `lmtps:inet:<host>:<port>` (secure lmtp with starttls)
# `lmtp:<kopano-host>:2003` (use kopano as mailstore)
POSTFIX_DAGENT=
# Set the mailbox size limit for all users. If set to zero, the size will be unlimited (default). Size is in bytes.
#
# empty => 0
POSTFIX_MAILBOX_SIZE_LIMIT=
# See https://docker-mailserver.github.io/docker-mailserver/latest/config/account-management/overview/#quotas
# 0 => Dovecot quota is disabled
# 1 => Dovecot quota is enabled
ENABLE_QUOTAS=1
# Set the message size limit for all users. If set to zero, the size will be unlimited (not recommended!). Size is in bytes.
#
# empty => 10240000 (~10 MB)
POSTFIX_MESSAGE_SIZE_LIMIT=
# Mails larger than this limit won't be scanned.
# ClamAV must be enabled (ENABLE_CLAMAV=1) for this.
#
# empty => 25M (25 MB)
CLAMAV_MESSAGE_SIZE_LIMIT=
# Enables regular pflogsumm mail reports.
# This is a new option. The old REPORT options are still supported for backwards compatibility. If this is not set and reports are enabled with the old options, logrotate will be used.
#
# not set => No report
# daily_cron => Daily report for the previous day
# logrotate => Full report based on the mail log when it is rotated
PFLOGSUMM_TRIGGER=
# Recipient address for pflogsumm reports.
#
# not set => Use REPORT_RECIPIENT or POSTMASTER_ADDRESS
# => Specify the recipient address(es)
PFLOGSUMM_RECIPIENT=
# Sender address (`FROM`) for pflogsumm reports if pflogsumm reports are enabled.
#
# not set => Use REPORT_SENDER
# => Specify the sender address
PFLOGSUMM_SENDER=
# Interval for logwatch report.
#
# none => No report is generated
# daily => Send a daily report
# weekly => Send a report every week
LOGWATCH_INTERVAL=
# Recipient address for logwatch reports if they are enabled.
#
# not set => Use REPORT_RECIPIENT or POSTMASTER_ADDRESS
# => Specify the recipient address(es)
LOGWATCH_RECIPIENT=
# Sender address (`FROM`) for logwatch reports if logwatch reports are enabled.
#
# not set => Use REPORT_SENDER
# => Specify the sender address
LOGWATCH_SENDER=
# Defines who receives reports if they are enabled.
# **empty** => ${POSTMASTER_ADDRESS}
# => Specify the recipient address
REPORT_RECIPIENT=
# Defines who sends reports if they are enabled.
# **empty** => mailserver-report@${DOMAINNAME}
# => Specify the sender address
REPORT_SENDER=
# Changes the interval in which log files are rotated
# **weekly** => Rotate log files weekly
# daily => Rotate log files daily
# monthly => Rotate log files monthly
#
# Note: This Variable actually controls logrotate inside the container
# and rotates the log files depending on this setting. The main log output is
# still available in its entirety via `docker logs mail` (Or your
# respective container name). If you want to control logrotation for
# the Docker-generated logfile see:
# https://docs.docker.com/config/containers/logging/configure/
#
# Note: This variable can also determine the interval for Postfix's log summary reports, see [`PFLOGSUMM_TRIGGER`](#pflogsumm_trigger).
LOGROTATE_INTERVAL=weekly
# Defines how many log files are kept by logrorate
LOGROTATE_COUNT=4
# If enabled, employs `reject_unknown_client_hostname` to sender restrictions in Postfix's configuration.
#
# - **0** => Disabled
# - 1 => Enabled
POSTFIX_REJECT_UNKNOWN_CLIENT_HOSTNAME=0
# Choose TCP/IP protocols for postfix to use
# **all** => All possible protocols.
# ipv4 => Use only IPv4 traffic. Most likely you want this behind Docker.
# ipv6 => Use only IPv6 traffic.
#
# Note: More details at http://www.postfix.org/postconf.5.html#inet_protocols
POSTFIX_INET_PROTOCOLS=all
# Enables MTA-STS support for outbound mail.
# More details: https://docker-mailserver.github.io/docker-mailserver/v13.3/config/best-practices/mta-sts/
# - **0** ==> MTA-STS disabled
# - 1 => MTA-STS enabled
ENABLE_MTA_STS=0
# Choose TCP/IP protocols for dovecot to use
# **all** => Listen on all interfaces
# ipv4 => Listen only on IPv4 interfaces. Most likely you want this behind Docker.
# ipv6 => Listen only on IPv6 interfaces.
#
# Note: More information at https://dovecot.org/doc/dovecot-example.conf
DOVECOT_INET_PROTOCOLS=all
# -----------------------------------------------
# --- SpamAssassin Section ----------------------
# -----------------------------------------------
ENABLE_SPAMASSASSIN=0
# KAM is a 3rd party SpamAssassin ruleset, provided by the McGrail Foundation.
# If SpamAssassin is enabled, KAM can be used in addition to the default ruleset.
# - **0** => KAM disabled
# - 1 => KAM enabled
#
# Note: only has an effect if `ENABLE_SPAMASSASSIN=1`
ENABLE_SPAMASSASSIN_KAM=0
# deliver spam messages to the inbox (tagged using SPAM_SUBJECT)
SPAMASSASSIN_SPAM_TO_INBOX=1
# spam messages will be moved in the Junk folder (SPAMASSASSIN_SPAM_TO_INBOX=1 required)
MOVE_SPAM_TO_JUNK=1
# spam messages will be marked as read
MARK_SPAM_AS_READ=0
# add 'spam info' headers at, or above this level
SA_TAG=2.0
# add 'spam detected' headers at, or above this level
SA_TAG2=6.31
# triggers spam evasive actions
SA_KILL=10.0
# -----------------------------------------------
# --- Fetchmail Section -------------------------
# -----------------------------------------------
ENABLE_FETCHMAIL=0
# The interval to fetch mail in seconds
FETCHMAIL_POLL=300
# Use multiple fetchmail instances (1 per poll entry in fetchmail.cf)
# Supports multiple IMAP IDLE connections when a server is used across multiple poll entries
# https://otremba.net/wiki/Fetchmail_(Debian)#Immediate_Download_via_IMAP_IDLE
FETCHMAIL_PARALLEL=0
# Enable or disable `getmail`.
#
# - **0** => Disabled
# - 1 => Enabled
ENABLE_GETMAIL=0
# The number of minutes for the interval. Min: 1; Default: 5.
GETMAIL_POLL=5
# -----------------------------------------------
# --- OAUTH2 Section ----------------------------
# -----------------------------------------------
# empty => OAUTH2 authentication is disabled
# 1 => OAUTH2 authentication is enabled
ENABLE_OAUTH2=
# Specify the user info endpoint URL of the oauth2 provider
# Example: https://oauth2.example.com/userinfo/
OAUTH2_INTROSPECTION_URL=
# -----------------------------------------------
# --- LDAP Section ------------------------------
# -----------------------------------------------
# A second container for the ldap service is necessary (i.e. https://hub.docker.com/r/bitnami/openldap/)
# empty => no
# yes => LDAP over TLS enabled for Postfix
LDAP_START_TLS=
# empty => mail.example.com
# Specify the `<dns-name>` / `<ip-address>` where the LDAP server is reachable via a URI like: `ldaps://mail.example.com`.
# Note: You must include the desired URI scheme (`ldap://`, `ldaps://`, `ldapi://`).
LDAP_SERVER_HOST=
# empty => ou=people,dc=domain,dc=com
# => e.g. LDAP_SEARCH_BASE=dc=mydomain,dc=local
LDAP_SEARCH_BASE=
# empty => cn=admin,dc=domain,dc=com
# => take a look at examples of SASL_LDAP_BIND_DN
LDAP_BIND_DN=
# empty** => admin
# => Specify the password to bind against ldap
LDAP_BIND_PW=
# e.g. `"(&(mail=%s)(mailEnabled=TRUE))"`
# => Specify how ldap should be asked for users
LDAP_QUERY_FILTER_USER=
# e.g. `"(&(mailGroupMember=%s)(mailEnabled=TRUE))"`
# => Specify how ldap should be asked for groups
LDAP_QUERY_FILTER_GROUP=
# e.g. `"(&(mailAlias=%s)(mailEnabled=TRUE))"`
# => Specify how ldap should be asked for aliases
LDAP_QUERY_FILTER_ALIAS=
# e.g. `"(&(|(mail=*@%s)(mailalias=*@%s)(mailGroupMember=*@%s))(mailEnabled=TRUE))"`
# => Specify how ldap should be asked for domains
LDAP_QUERY_FILTER_DOMAIN=
# -----------------------------------------------
# --- Dovecot Section ---------------------------
# -----------------------------------------------
# empty => no
# yes => LDAP over TLS enabled for Dovecot
DOVECOT_TLS=
# e.g. `"(&(objectClass=PostfixBookMailAccount)(uniqueIdentifier=%n))"`
DOVECOT_USER_FILTER=
# e.g. `"(&(objectClass=PostfixBookMailAccount)(uniqueIdentifier=%n))"`
DOVECOT_PASS_FILTER=
# Define the mailbox format to be used
# default is maildir, supported values are: sdbox, mdbox, maildir
DOVECOT_MAILBOX_FORMAT=maildir
# empty => no
# yes => Allow bind authentication for LDAP
# https://doc.dovecot.org/2.4.0/core/config/auth/databases/ldap.html#authentication-bind
DOVECOT_AUTH_BIND=
# -----------------------------------------------
# --- Postgrey Section --------------------------
# -----------------------------------------------
ENABLE_POSTGREY=0
# greylist for N seconds
POSTGREY_DELAY=300
# delete entries older than N days since the last time that they have been seen
POSTGREY_MAX_AGE=35
# response when a mail is greylisted
POSTGREY_TEXT="Delayed by Postgrey"
# whitelist host after N successful deliveries (N=0 to disable whitelisting)
POSTGREY_AUTO_WHITELIST_CLIENTS=5
# -----------------------------------------------
# --- SASL Section ------------------------------
# -----------------------------------------------
ENABLE_SASLAUTHD=0
# empty => ldap
# `ldap` => authenticate against ldap server
# `rimap` => authenticate against imap server
SASLAUTHD_MECHANISMS=
# empty => None
# e.g. with SASLAUTHD_MECHANISMS rimap you need to specify the ip-address/servername of the imap server ==> xxx.xxx.xxx.xxx
SASLAUTHD_MECH_OPTIONS=
# empty => Use value of LDAP_SERVER_HOST
# Note: You must include the desired URI scheme (`ldap://`, `ldaps://`, `ldapi://`).
SASLAUTHD_LDAP_SERVER=
# empty => Use value of LDAP_BIND_DN
# specify an object with privileges to search the directory tree
# e.g. active directory: SASLAUTHD_LDAP_BIND_DN=cn=Administrator,cn=Users,dc=mydomain,dc=net
# e.g. openldap: SASLAUTHD_LDAP_BIND_DN=cn=admin,dc=mydomain,dc=net
SASLAUTHD_LDAP_BIND_DN=
# empty => Use value of LDAP_BIND_PW
SASLAUTHD_LDAP_PASSWORD=
# empty => Use value of LDAP_SEARCH_BASE
# specify the search base
SASLAUTHD_LDAP_SEARCH_BASE=
# empty => default filter `(&(uniqueIdentifier=%u)(mailEnabled=TRUE))`
# e.g. for active directory: `(&(sAMAccountName=%U)(objectClass=person))`
# e.g. for openldap: `(&(uid=%U)(objectClass=person))`
SASLAUTHD_LDAP_FILTER=
# empty => no
# yes => LDAP over TLS enabled for SASL
# If set to yes, the protocol in SASLAUTHD_LDAP_SERVER must be ldap:// or missing.
SASLAUTHD_LDAP_START_TLS=
# empty => no
# yes => Require and verify server certificate
# If yes you must/could specify SASLAUTHD_LDAP_TLS_CACERT_FILE or SASLAUTHD_LDAP_TLS_CACERT_DIR.
SASLAUTHD_LDAP_TLS_CHECK_PEER=
# File containing CA (Certificate Authority) certificate(s).
# empty => Nothing is added to the configuration
# Any value => Fills the `ldap_tls_cacert_file` option
SASLAUTHD_LDAP_TLS_CACERT_FILE=
# Path to directory with CA (Certificate Authority) certificates.
# empty => Nothing is added to the configuration
# Any value => Fills the `ldap_tls_cacert_dir` option
SASLAUTHD_LDAP_TLS_CACERT_DIR=
# Specify what password attribute to use for password verification.
# empty => Nothing is added to the configuration but the documentation says it is `userPassword` by default.
# Any value => Fills the `ldap_password_attr` option
SASLAUTHD_LDAP_PASSWORD_ATTR=
# empty => `bind` will be used as a default value
# `fastbind` => The fastbind method is used
# `custom` => The custom method uses userPassword attribute to verify the password
SASLAUTHD_LDAP_AUTH_METHOD=
# Specify the authentication mechanism for SASL bind
# empty => Nothing is added to the configuration
# Any value => Fills the `ldap_mech` option
SASLAUTHD_LDAP_MECH=
# -----------------------------------------------
# --- SRS Section -------------------------------
# -----------------------------------------------
# envelope_sender => Rewrite only envelope sender address (default)
# header_sender => Rewrite only header sender (not recommended)
# envelope_sender,header_sender => Rewrite both senders
# An email has an "envelope" sender (indicating the sending server) and a
# "header" sender (indicating who sent it). More strict SPF policies may require
# you to replace both instead of just the envelope sender.
SRS_SENDER_CLASSES=envelope_sender
# empty => Envelope sender will be rewritten for all domains
# provide comma separated list of domains to exclude from rewriting
SRS_EXCLUDE_DOMAINS=
# empty => generated when the image is built
# provide a secret to use in base64
# you may specify multiple keys, comma separated. the first one is used for
# signing and the remaining will be used for verification. this is how you
# rotate and expire keys
SRS_SECRET=
# -----------------------------------------------
# --- Default Relay Host Section ----------------
# -----------------------------------------------
# Setup relaying all mail through a default relay host
#
# Set a default host to relay all mail through (optionally include a port)
# Example: [mail.example.com]:587
DEFAULT_RELAY_HOST=
# -----------------------------------------------
# --- Multi-Domain Relay Section ----------------
# -----------------------------------------------
# Setup relaying for multiple domains based on the domain name of the sender
# optionally uses usernames and passwords in postfix-sasl-password.cf and relay host mappings in postfix-relaymap.cf
#
# Set a default host to relay mail through
# Example: mail.example.com
RELAY_HOST=
# empty => 25
# default port to relay mail
RELAY_PORT=25
# -----------------------------------------------
# --- Relay Host Credentials Section ------------
# -----------------------------------------------
# Configure a relay user and password to use with RELAY_HOST / DEFAULT_RELAY_HOST
# empty => no default
RELAY_USER=
# empty => no default
RELAY_PASSWORD=

3
memos/README.md Normal file
View file

@ -0,0 +1,3 @@
# Compose file for Memos
## Environment Variables
- POSTGRES_PASSWORD - database password

43
memos/compose.yaml Normal file
View file

@ -0,0 +1,43 @@
services:
memos:
image: neosmemo/memos:stable
container_name: memos
restart: unless-stopped
networks:
- default
- proxy
depends_on:
- memos_db
volumes:
- memos_data:/var/opt/memos
environment:
- MEMOS_DRIVER=postgres
- MEMOS_DSN=user=memos password=${POSTGRES_PASSWORD} dbname=memosdb host=memos_db sslmode=disable
labels:
caddy: memos.ferngarden.net
caddy.import: internal
caddy.reverse_proxy: "{{upstreams 5230}}"
memos_db:
image: postgres:16.1
container_name: memos_db
restart: unless-stopped
networks:
- default
volumes:
- memos_db:/var/lib/postgresql/data/
environment:
- POSTGRES_USER=memos
- POSTGRES_DB=memosdb
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
networks:
default:
proxy:
external: true
volumes:
memos_db:
name: memos_db
memos_data:
name: memos_data

34
metrics/compose.yaml Normal file
View file

@ -0,0 +1,34 @@
services:
docker_socket_proxy:
image: ghcr.io/tecnativa/docker-socket-proxy:latest
container_name: docker_socket_proxy
environment:
- CONTAINERS=1 # Allow access to viewing containers
- INFO=1
- POST=0 # Disallow any POST operations (effectively read-only)
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro # Mounted as read-only
restart: unless-stopped
ports:
- 2375:2375
networks:
- default
- metrics
glances:
image: nicolargo/glances:latest
container_name: glances
restart: always
pid: host
environment:
- "GLANCES_OPT=-w"
ports:
- 61208:61208
networks:
- default
- metrics
networks:
default:
metrics:
name: metrics

1
minecraft/README.md Normal file
View file

@ -0,0 +1 @@
# Compose file for Minecraft

63
minecraft/compose.yaml Normal file
View file

@ -0,0 +1,63 @@
services:
minecraft_proxy:
image: itzg/mc-proxy
container_name: minecraft_proxy
restart: unless-stopped
volumes:
- velocity_config:/config
- velocity_server:/server
networks:
- default
ports:
- 25565:25565
environment:
- TYPE=VELOCITY
- MINECRAFT_VERSION=1.21.5
minecraft_server_mc:
image: itzg/minecraft-server
container_name: minecraft_server_mc
hostname: mc
restart: unless-stopped
volumes:
- minecraft_server_mc:/data
networks:
- default
depends_on:
- minecraft_proxy
env_file:
- server.env
environment:
- MOTD=meow
- ICON=https://git.fern.garden/fern/stacks/raw/branch/main/minecraft/server-icons/mc.png
- PLUGINS=https://dev.bukkit.org/projects/dead-chest/files/latest
minecraft_server_bob:
image: itzg/minecraft-server
container_name: minecraft_server_bob
hostname: bob
restart: unless-stopped
volumes:
- minecraft_server_bob:/data
depends_on:
- minecraft_proxy
env_file:
- server.env
environment:
- MOTD=it's bob's world, we're just living in it
- ICON=https://git.fern.garden/fern/stacks/raw/branch/main/minecraft/server-icons/bob.png
networks:
default:
volumes:
minecraft_webadmin_db:
name: minecraft_webadmin_db
minecraft_server_mc:
name: minecraft_server_mc
minecraft_server_bob:
name: minecraft_server_bob
velocity_config:
name: velocity_config
velocity_server:
name: velocity_server

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 708 B

24
minecraft/server.env Normal file
View file

@ -0,0 +1,24 @@
EULA=TRUE
TZ=Australia/Perth
TYPE=PAPER
RCON_PASSWORD=${RCON_PASSWORD}
PAPER_CHANNEL=experimental
VERSION=1.21.5
ENABLE_ROLLING_LOGS=true
LOG_TIMESTAMP=true
OVERRIDE_ICON=TRUE
RESOURCE_PACK=https://cdn.modrinth.com/data/4YkvO5Rp/versions/y8c31PGb/Whimscape_1.20.2-1.21.5_r3.zip
RESOURCE_PACK_SHA1=c486d46b7f79d3aa187e7288385858220c37b05b
ENABLE_WHITELIST=true
ONLINE_MODE=FALSE
SNOOPER_ENABLED=false
USE_AIKAR_FLAGS=true
MAX_MEMORY=6G
DIFFICULTY=normal
MAX_PLAYERS=10
SPAWN_PROTECTION=0
PVP=false
VIEW_DISTANCE=24
SIMULATION_DISTANCE=12
MODRINTH_PROJECTS=essentialsx,essentialsx-antibuild,essentialsx-chat-module,essentialsx-protect,essentialsx-spawn,luckperms
SPIGET_RESOURCES=40313

6
miniflux/README.md Normal file
View file

@ -0,0 +1,6 @@
# Compose file for Miniflux
## Environment Variables
- POSTGRES_PASSWORD - database password
- ADMIN_PASSWORD - admin user password
- OAUTH2_CLIENT_ID - authentik client ID
- OAUTH2_CLIENT_SECRET - authentik client secret

54
miniflux/compose.yaml Normal file
View file

@ -0,0 +1,54 @@
services:
miniflux:
image: miniflux/miniflux:latest
container_name: miniflux
restart: unless-stopped
networks:
- default
- proxy
depends_on:
miniflux_db:
condition: service_healthy
environment:
- DATABASE_URL=postgres://miniflux:${POSTGRES_PASSWORD}@miniflux_db/miniflux?sslmode=disable
- RUN_MIGRATIONS=1
- CREATE_ADMIN=1
- DISABLE_LOCAL_AUTH=true
- ADMIN_USERNAME=fern
- ADMIN_PASSWORD=${ADMIN_PASSWORD}
- OAUTH2_PROVIDER=oidc
- OAUTH2_CLIENT_ID=${OAUTH2_CLIENT_ID}
- OAUTH2_CLIENT_SECRET=${OAUTH2_CLIENT_SECRET}
- OAUTH2_REDIRECT_URL=https://rss.ferngarden.net/oauth2/oidc/callback
- OAUTH2_OIDC_DISCOVERY_ENDPOINT=https://auth.fern.garden/application/o/miniflux/
- OAUTH2_USER_CREATION=1
labels:
caddy: rss.ferngarden.net
caddy.import: internal
caddy.reverse_proxy: "{{upstreams 8080}}"
miniflux_db:
image: postgres:17-alpine
container_name: miniflux_db
restart: unless-stopped
networks:
- default
environment:
- POSTGRES_USER=miniflux
- POSTGRES_DB=miniflux
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
volumes:
- miniflux_db:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready", "-U", "miniflux"]
interval: 10s
start_period: 30s
networks:
default:
proxy:
external: true
volumes:
miniflux_db:
name: miniflux_db

4
navidrome/README.md Normal file
View file

@ -0,0 +1,4 @@
# Compose file for Navidrome
## Environment Variables
- ND_LASTFM_APIKEY - last.fm API key
- ND_LASTFM_SECRET - last.fm API secret

30
navidrome/compose.yaml Normal file
View file

@ -0,0 +1,30 @@
services:
navidrome:
image: deluan/navidrome:latest
container_name: navidrome
networks:
- default
- proxy
restart: unless-stopped
environment:
- ND_BASEURL=https://music.fern.garden
- ND_REVERSEPROXYUSERHEADER=X-authentik-username
- ND_REVERSEPROXYWHITELIST=0.0.0.0/0
- ND_LASTFM_APIKEY=${ND_LASTFM_APIKEY}
- ND_LASTFM_SECRET=${ND_LASTFM_SECRET}
- ND_PLAYLISTSPATH=Playlists
volumes:
- navidrome_data:/data
- /media/media/beets:/music:ro
labels:
caddy: music.fern.garden
caddy.import: authentik
networks:
default:
proxy:
external: true
volumes:
navidrome_data:
name: navidrome_data

3
netatalk/README.md Normal file
View file

@ -0,0 +1,3 @@
# Compose file for Netatalk
## Environment Variables
- AFP_PASS - file share password

20
netatalk/compose.yaml Normal file
View file

@ -0,0 +1,20 @@
services:
netatalk:
image: netatalk/netatalk:latest
container_name: netatalk
network_mode: host
cap_add:
- NET_ADMIN
volumes:
- netatalk_backup:/mnt/afpbackup
- /srv/netatalk:/mnt/afpshare
- /var/run/dbus:/var/run/dbus
environment:
- AFP_USER=fern
- AFP_PASS=${AFP_PASS}
- AFP_GROUP=afpusers
- ATALKD_INTERFACE=eth0
- TZ=Australia/Perth
volumes:
netatalk_backup:

1
nextcloud-aio/README.md Normal file
View file

@ -0,0 +1 @@
# Compose file for Nextcloud All-In-One

View file

@ -0,0 +1,24 @@
services:
nextcloud-aio-mastercontainer:
image: ghcr.io/nextcloud-releases/all-in-one:latest
container_name: nextcloud-aio-mastercontainer
init: true
network_mode: bridge
restart: always
volumes:
- nextcloud_aio_mastercontainer:/mnt/docker-aio-config
- /var/run/docker.sock:/var/run/docker.sock:ro
ports:
- 8080:8080
environment:
APACHE_PORT: 11000
APACHE_IP_BINDING: 0.0.0.0
APACHE_ADDITIONAL_NETWORK: proxy
labels:
caddy: cloud.ferngarden.net
caddy.import: internal
caddy.reverse_proxy: "nextcloud-aio-apache:11000"
volumes:
nextcloud_aio_mastercontainer:
name: nextcloud_aio_mastercontainer

6
notifications/README.md Normal file
View file

@ -0,0 +1,6 @@
# Compose file for notifications stack
## Services
- ntfy.sh
- Mollysocket
## Environment Variables
- MOLLY_VAPID_PRIVKEY - authorisation key

View file

@ -0,0 +1,83 @@
services:
ntfy:
image: binwiederhier/ntfy
container_name: ntfy
networks:
- default
- proxy
command: serve
volumes:
- ntfy_cache:/var/cache/ntfy
- ntfy_config:/etc/ntfy
- ntfy_data:/var/lib/ntfy
healthcheck:
test: ["CMD-SHELL", "wget -q --tries=1 http://localhost:2586/v1/health -O - | grep -Eo '\"healthy\"\\s*:\\s*true' || exit 1"]
interval: 60s
timeout: 10s
retries: 3
start_period: 40s
restart: unless-stopped
labels:
caddy: ntfy.fern.garden
caddy.reverse_proxy: "{{upstreams 2586}}"
mollysocket:
image: ghcr.io/mollyim/mollysocket:1
container_name: mollysocket
networks:
- default
- proxy
restart: unless-stopped
volumes:
- mollysocket_data:/data
working_dir: /data
command: server
environment:
- MOLLY_DB=/data/mollysocket.db
- MOLLY_ALLOWED_ENDPOINTS=["https://ntfy.fern.garden"]
- MOLLY_ALLOWED_UUIDS=["*"]
- MOLLY_VAPID_PRIVKEY=${MOLLY_VAPID_PRIVKEY}
- MOLLY_HOST=0.0.0.0
- MOLLY_PORT=8020
- RUST_LOG=info
labels:
caddy: mollysocket.fern.garden
caddy.reverse_proxy: "{{upstreams 8020}}"
apprise-api:
image: lscr.io/linuxserver/apprise-api:latest
container_name: apprise-api
environment:
- PUID=1000
- PGID=1000
- TZ=Australia/Perth
networks:
- default
- proxy
volumes:
- apprise-api_config:/config
- apprise-api_attachments:/attachments
restart: unless-stopped
labels:
caddy: apprise.ferngarden.net
caddy.import: internal
caddy.reverse_proxy: '{{ upstreams 8000 }}'
networks:
default:
proxy:
external: true
volumes:
ntfy_cache:
name: ntfy_cache
ntfy_config:
name: ntfy_config
ntfy_data:
name: ntfy_data
mollysocket_data:
name: mollysocket_data
apprise-api_config:
name: apprise-api_config
apprise-api_attachments:
name: apprise-api_attachments

6
paperless/README.md Normal file
View file

@ -0,0 +1,6 @@
# Compose file for [template]
## Environment Variables
- POSTGRES_PASSWORD - database password
- PAPERLESS_SECRET_KEY - session token key
- AUTHENTIK_CLIENT_ID - Authentik client ID
- AUTHENTIK_CLIENT_SECRET - Authentik client secret

87
paperless/compose.yaml Normal file
View file

@ -0,0 +1,87 @@
services:
paperless_redis:
image: docker.io/library/redis:8
container_name: paperless_redis
restart: unless-stopped
volumes:
- paperless_redis:/data
networks:
- default
paperless_db:
image: docker.io/library/postgres:17
container_name: paperless_db
restart: unless-stopped
volumes:
- paperless_db:/var/lib/postgresql/data
environment:
POSTGRES_DB: paperless
POSTGRES_USER: paperless
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
networks:
- default
paperless:
image: ghcr.io/paperless-ngx/paperless-ngx:latest
container_name: paperless
restart: unless-stopped
depends_on:
- paperless_db
- paperless_redis
volumes:
- paperless_data:/usr/src/paperless/data
- paperless_media:/usr/src/paperless/media
environment:
PAPERLESS_REDIS: redis://paperless_redis:6379
PAPERLESS_DBHOST: paperless_db
PAPERLESS_DBPASS: ${POSTGRES_PASSWORD}
USERMAP_UID: 1000
USERMAP_GID: 1000
PAPERLESS_URL: https://paperless.ferngarden.net
PAPERLESS_TIME_ZONE: Australia/Perth
PAPERLESS_SECRET_KEY: ${PAPERLESS_SECRET_KEY}
PAPERLESS_ACCOUNT_ALLOW_SIGNUPS: true
PAPERLESS_SOCIAL_AUTO_SIGNUP: true
PAPERLESS_SOCIALACCOUNT_ALLOW_SIGNUPS: true
PAPERLESS_DISABLE_REGULAR_LOGIN: true
PAPERLESS_REDIRECT_LOGIN_TO_SSO: true
PAPERLESS_APPS: allauth.socialaccount.providers.openid_connect
PAPERLESS_SOCIALACCOUNT_PROVIDERS: >
{
"openid_connect": {
"APPS": [
{
"provider_id": "authentik",
"name": "Authentik",
"client_id": "${AUTHENTIK_CLIENT_ID}",
"secret": "${AUTHENTIK_CLIENT_SECRET}",
"settings": {
"server_url": "https://auth.fern.garden/application/o/paperless/.well-known/openid-configuration"
}
}
],
"OAUTH_PKCE_ENABLED": "True"
}
}
networks:
- default
- proxy
labels:
caddy: paperless.ferngarden.net
caddy.import: internal
caddy.reverse_proxy: "{{upstreams 8000}}"
networks:
default:
proxy:
external: true
volumes:
paperless_data:
name: paperless_data
paperless_media:
name: paperless_media
paperless_db:
name: paperless_db
paperless_redis:
name: paperless_redis

5
qbittorrent/README.md Normal file
View file

@ -0,0 +1,5 @@
# Compose file for qBittorrent
## Environment Variables
- WIREGUARD_PRIVATE_KEY - VPN private key
- QBITTORRENT_PASS - qbittorrent user password
- GLUETUN_APIKEY - gluetun control server API key

138
qbittorrent/compose.yaml Normal file
View file

@ -0,0 +1,138 @@
services:
qbittorrent:
image: lscr.io/linuxserver/qbittorrent:latest
container_name: qbittorrent
restart: unless-stopped
network_mode: service:qbittorrent_gluetun
volumes:
- qbittorrent_config:/config
- /media:/media
environment:
- WEBUI_PORT=8080
- PUID=1000
- PGID=1800
- TZ=Australia/Perth
healthcheck:
test: ["CMD-SHELL", "curl -sf https://api.ipify.org || exit 1"]
interval: 30s
timeout: 10s
retries: 3
depends_on:
qbittorrent_gluetun:
condition: service_healthy
qbittorrent_gluetun:
image: qmcgaw/gluetun
container_name: qbittorrent_gluetun
restart: unless-stopped
networks:
- default
- proxy
- media
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
volumes:
- qbittorrent_gluetun_auth:/gluetun/auth
environment:
- VPN_SERVICE_PROVIDER=protonvpn
- VPN_TYPE=wireguard
- VPN_PORT_FORWARDING=on
- GLUETUN_HTTP_CONTROL_SERVER_ENABLE=on
- SERVER_COUNTRIES=Australia
- WIREGUARD_ADDRESSES=10.2.0.2/32
- WIREGUARD_PRIVATE_KEY=${WIREGUARD_PRIVATE_KEY}
- BLOCK_MALICIOUS=off
labels:
caddy: qbittorrent.ferngarden.net
caddy.import: internal
caddy.reverse_proxy: "{{upstreams 8080}}"
qbittorrent_qsticky:
image: ghcr.io/monstermuffin/qsticky:latest
container_name: qbittorrent_qsticky
networks:
- default
environment:
- QBITTORRENT_HOST=qbittorrent_gluetun
- QBITTORRENT_HTTPS=false
- QBITTORRENT_PORT=8080
- QBITTORRENT_USER=fern
- QBITTORRENT_PASS=${QBITTORRENT_PASS}
- GLUETUN_HOST=qbittorrent_gluetun
- GLUETUN_AUTH_TYPE=apikey
- GLUETUN_APIKEY=${GLUETUN_APIKEY}
- LOG_LEVEL=INFO
healthcheck:
test: ["CMD", "python3", "-c", "import json; exit(0 if json.load(open('/app/health/status.json'))['healthy'] else 1)"]
interval: 30s
timeout: 10s
retries: 3
restart: unless-stopped
# qbittorrent_mamapi:
# image: elforkhead/mamapi
# container_name: qbittorrent_mamapi
# restart: unless-stopped
# network_mode: service:qbittorrent_gluetun
# environment:
# - TZ=Australia/Perth
# - MAM_ID=${MAM_ID}
# volumes:
# - qbittorrent_mamapi_data:/data
# depends_on:
# qbittorrent_gluetun:
# condition: service_healthy
cross-seed:
image: ghcr.io/cross-seed/cross-seed:6
container_name: cross-seed
user: 1000:1800
volumes:
- cross-seed_config:/config
- /media:/media
networks:
- default
- media
command: daemon
restart: unless-stopped
fertilizer:
image: ghcr.io/moleculekayak/fertilizer:latest
container_name: fertilizer
user: 1000:1800
networks:
default:
ipv4_address: 172.16.7.4
volumes:
- qbittorrent_config:/torrents:ro
- /media:/media
environment:
- OPS_KEY=${OPS_KEY}
- RED_KEY=${RED_KEY}
- INJECT_TORRENTS=true
- INJECTION_LINK_DIRECTORY=/media/downloads/fertilizer/linked-data
- QBITTORRENT_URL=http://fern:${QBITTORRENT_PASS}@qbittorrent_gluetun:8080
command: fertilizer -o /media/downloads/fertilizer/torrent-files -i /torrents/qBittorrent/BT_backup --server
networks:
default:
ipam:
driver: default
config:
- subnet: 172.16.7.0/24
proxy:
external: true
media:
external: true
volumes:
qbittorrent_config:
name: qbittorrent_config
qbittorrent_mamapi_data:
name: qbittorrent_mamapi_data
qbittorrent_gluetun_auth:
name: qbittorrent_gluetun_auth
cross-seed_config:
name: cross-seed_config

590
resources.toml Normal file
View file

@ -0,0 +1,590 @@
[[server]]
name = "docker.local"
tags = ["spoonbill"]
[server.config]
address = "https://periphery:8120"
enabled = true
##
[[server]]
name = "minecraft.local"
tags = ["spoonbill"]
[server.config]
address = "https://10.0.1.105:8120"
enabled = true
##
[[server]]
name = "weebill.local"
tags = ["weebill"]
[server.config]
address = "https://10.0.1.4:8120"
enabled = true
##
[[stack]]
name = "13ft"
tags = ["internal"]
[stack.config]
server = "docker.local"
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "13ft"
##
[[stack]]
name = "arr"
tags = ["internal", "media"]
[stack.config]
server = "docker.local"
links = [
"https://bazarr.ferngarden.net/",
"https://jackett.ferngarden.net/",
"https://lidarr.ferngarden.net/",
"https://prowlarr.ferngarden.net/",
"https://radarr.ferngarden.net/",
"https://readarr-audiobooks.ferngarden.net/",
"https://readarr-ebooks.ferngarden.net/",
"https://sonarr.ferngarden.net/"
]
auto_update = true
linked_repo = "forgejo"
run_directory = "arr"
environment = """
QBITTORRENT__PASSWORD=[[QBITTORRENT_PASSWORD]]
"""
##
[[stack]]
name = "audiobookshelf"
tags = ["media", "public"]
[stack.config]
server = "docker.local"
links = [
"https://audiobookshelf.fern.garden"
]
auto_update = true
linked_repo = "forgejo"
run_directory = "audiobookshelf"
##
[[stack]]
name = "authentik"
tags = ["reverse-proxy", "public"]
[stack.config]
server = "docker.local"
links = ["https://auth.fern.garden"]
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "authentik"
environment = """
POSTGRES_PASSWORD=[[AUTHENTIK_DB_PASSWORD]]
AUTHENTIK_SECRET_KEY=[[AUTHENTIK_SECRET_KEY]]
AUTHENTIK_EMAIL__PASSWORD=[[SMTP_PASSWORD]]
AUTHENTIK_LDAP_TOKEN=[[AUTHENTIK_LDAP_TOKEN]]
AUTHENTIK_PROXY_TOKEN=[[AUTHENTIK_PROXY_TOKEN]]
AUTHENTIK_VERSION=2025.6
"""
##
[[stack]]
name = "caddy"
tags = ["reverse-proxy", "public"]
[stack.config]
server = "docker.local"
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "caddy"
environment = """
CF_API_TOKEN=[[CLOUDFLARE_API_TOKEN]]
"""
##
[[stack]]
name = "calibre"
tags = ["media", "public"]
[stack.config]
server = "docker.local"
links = [
"https://calibre.ferngarden.net",
"https://books.fern.garden"
]
auto_update = true
linked_repo = "forgejo"
run_directory = "calibre"
##
[[stack]]
name = "dozzle"
tags = ["internal"]
[stack.config]
server = "docker.local"
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "dozzle"
##
[[stack]]
name = "forgejo"
tags = ["public"]
[stack.config]
server = "docker.local"
links = ["https://git.fern.garden"]
auto_update = true
linked_repo = "forgejo"
run_directory = "forgejo"
environment = """
POSTGRES_PASSWORD=[[FORGEJO_DB_PASSWORD]]
"""
##
[[stack]]
name = "grocy"
tags = ["internal"]
[stack.config]
server = "docker.local"
links = ["https://grocy.ferngarden.net"]
auto_update = true
linked_repo = "forgejo"
run_directory = "grocy"
##
[[stack]]
name = "homebox"
tags = ["internal"]
[stack.config]
server = "docker.local"
links = [
"https://homebox.ferngarden.net"
]
auto_update = true
linked_repo = "forgejo"
run_directory = "homebox"
##
[[stack]]
name = "homepage"
tags = ["internal", "metrics"]
[stack.config]
server = "docker.local"
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "homepage"
##
[[stack]]
name = "immich"
tags = ["internal"]
[stack.config]
server = "docker.local"
links = [
"https://photos.ferngarden.net"
]
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "immich"
environment = """
DB_PASSWORD=[[IMMICH_DB_PASSWORD]]
"""
##
[[stack]]
name = "it-tools"
tags = ["internal"]
[stack.config]
server = "docker.local"
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "it-tools"
##
[[stack]]
name = "jellyfin"
tags = ["media", "public"]
[stack.config]
server = "docker.local"
links = [
"https://jellyfin.fern.garden",
"https://jellystat.ferngarden.net"
]
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "jellyfin"
environment = """
JELLYSTAT_JWT_SECRET=[[JELLYSTAT_JWT_SECRET]]
JELLYSTAT_POSTGRES_PASSWORD=[[JELLYSTAT_DB_PASSWORD]]
"""
##
[[stack]]
name = "komga"
tags = ["media", "public"]
[stack.config]
server = "docker.local"
links = ["https:/comics.fern.garden"]
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "komga"
##
[[stack]]
name = "mailserver"
tags = ["internal"]
[stack.config]
server = "docker.local"
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "mailserver"
##
[[stack]]
name = "memos"
tags = ["internal"]
[stack.config]
server = "docker.local"
links = ["https://memos.ferngarden.net"]
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "memos"
environment = """
POSTGRES_PASSWORD=[[MEMOS_DB_PASSWORD]]
"""
##
[[stack]]
name = "metrics_docker_local"
tags = ["internal", "metrics"]
[stack.config]
server = "docker.local"
linked_repo = "forgejo"
run_directory = "metrics"
##
[[stack]]
name = "metrics_minecraft_local"
tags = ["internal", "metrics"]
[stack.config]
server = "minecraft.local"
linked_repo = "forgejo"
run_directory = "metrics"
##
[[stack]]
name = "metrics_weebill_local"
tags = ["internal", "metrics"]
[stack.config]
server = "weebill.local"
linked_repo = "forgejo"
run_directory = "metrics"
##
[[stack]]
name = "minecraft"
tags = ["public"]
[stack.config]
server = "minecraft.local"
auto_update = true
linked_repo = "forgejo"
reclone = true
run_directory = "minecraft"
environment = """
RCON_PASSWORD=[[MINECRAFT_RCON_PASSWORD]]
"""
##
[[stack]]
name = "miniflux"
tags = ["internal"]
[stack.config]
server = "docker.local"
links = ["https://rss.ferngarden.net"]
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "miniflux"
environment = """
POSTGRES_PASSWORD=[[MINIFLUX_DB_PASSWORD]]
ADMIN_PASSWORD=[[MINIFLUX_ADMIN_PASSWORD]]
OAUTH2_CLIENT_ID=[[MINIFLUX_OIDC_CLIENT_ID]]
OAUTH2_CLIENT_SECRET=[[MINIFLUX_OIDC_CLIENT_SECRET]]
"""
##
[[stack]]
name = "navidrome"
tags = ["media", "public"]
[stack.config]
server = "docker.local"
links = ["https://music.fern.garden"]
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "navidrome"
environment = """
ND_LASTFM_APIKEY=[[NAVIDROME_LASTFM_API_KEY]]
ND_LASTFM_SECRET=[[NAVIDROME_LASTFM_API_SECRET]]
"""
##
[[stack]]
name = "netatalk"
tags = ["internal"]
[stack.config]
server = "weebill.local"
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "netatalk"
environment = """
AFP_PASS=[[NETATALK_AFP_PASSWORD]]
"""
##
[[stack]]
name = "nextcloud-aio"
tags = ["internal"]
[stack.config]
server = "docker.local"
links = [
"https://cloud.ferngarden.net",
"https://docker.local:8080"
]
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "nextcloud-aio"
##
[[stack]]
name = "notifications"
tags = ["public"]
[stack.config]
server = "docker.local"
links = [
"https://ntfy.fern.garden",
"https://mollysocket.fern.garden"
]
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "notifications"
environment = """
MOLLY_VAPID_PRIVKEY=[[MOLLY_VAPID_PRIVKEY]]
"""
##
[[stack]]
name = "paperless"
tags = ["internal"]
[stack.config]
server = "docker.local"
links = [
"https://paperless.ferngarden.net"
]
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "paperless"
environment = """
POSTGRES_PASSWORD=[[PAPERLESS_DB_PASSWORD]]
PAPERLESS_SECRET_KEY=[[PAPERLESS_SECRET_KEY]]
AUTHENTIK_CLIENT_ID=[[PAPERLESS_OIDC_CLIENT_ID]]
AUTHENTIK_CLIENT_SECRET=[[PAPERLESS_OIDC_CLIENT_SECRET]]
"""
##
[[stack]]
name = "qbittorrent"
tags = ["internal", "media"]
[stack.config]
server = "docker.local"
links = [
"https://qbittorrent.ferngarden.net"
]
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "qbittorrent"
environment = """
WIREGUARD_PRIVATE_KEY=[[QBITTORRENT_WIREGUARD_PRIVATE_KEY]]
QBITTORRENT_PASS=[[QBITTORRENT_PASSWORD]]
GLUETUN_APIKEY=[[QBITTORRENT_GLUETUN_API_KEY]]
MAM_ID=[[MAM_ID]]
OPS_KEY=[[OPS_KEY]]
RED_KEY=[[RED_KEY]]
"""
##
[[stack]]
name = "romm"
tags = ["public", "media"]
[stack.config]
server = "docker.local"
links = ["https://games.fern.garden"]
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "romm"
environment = """
MARIADB_PASSWORD=[[ROMM_DB_PASSWORD]]
MARIADB_ROOT_PASSWORD=[[ROMM_DB_ROOT_PASSWORD]]
ROMM_AUTH_SECRET_KEY=[[ROMM_AUTH_KEY]]
IGDB_CLIENT_ID=[[IGDB_CLIENT_ID]]
IGDB_CLIENT_SECRET=[[IGDB_CLIENT_SECRET]]
SCREENSCRAPER_PASSWORD=[[SCREENSCRAPER_PASSWORD]]
STEAMGRIDDB_API_KEY=[[STEAMGRIDDB_API_KEY]]
MOBYGAMES_API_KEY=[[MOBYGAMES_API_KEY]]
OIDC_CLIENT_ID=[[ROMM_OIDC_CLIENT_ID]]
OIDC_CLIENT_SECRET=[[ROMM_OIDC_CLIENT_SECRET]]
"""
##
[[stack]]
name = "stash"
tags = ["internal", "media"]
[stack.config]
server = "docker.local"
links = ["https://stash.ferngarden.net"]
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "stash"
##
[[stack]]
name = "stirling-pdf"
tags = ["internal"]
[stack.config]
server = "docker.local"
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "stirling-pdf"
##
[[stack]]
name = "synapse"
tags = ["public"]
[stack.config]
server = "docker.local"
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "synapse"
##
[[stack]]
name = "vaultwarden"
tags = ["internal"]
[stack.config]
server = "docker.local"
links = ["https://vault.ferngarden.net"]
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "vaultwarden"
environment = """
SMTP_PASSWORD=[[SMTP_PASSWORD]]
"""
##
[[stack]]
name = "wallos"
tags = ["internal"]
[stack.config]
server = "docker.local"
links = [
"https://wallos.ferngarden.net"
]
poll_for_updates = true
auto_update = true
linked_repo = "forgejo"
run_directory = "wallos"
##
[[build]]
name = "caddy"
[build.config]
builder = "docker.local"
version = "2.10.0"
auto_increment_version = false
linked_repo = "forgejo"
build_path = "caddy"
image_registry.domain = "git.fern.garden"
image_registry.account = "fern"
##
[[repo]]
name = "forgejo"
[repo.config]
server = "docker.local"
builder = "docker.local"
git_provider = "git.fern.garden"
git_account = "fern"
repo = "fern/stacks"
##
[[builder]]
name = "docker.local"
[builder.config]
type = "Server"
params.server_id = "docker.local"
##
[[resource_sync]]
name = "forgejo"
[resource_sync.config]
linked_repo = "forgejo"
resource_path = ["resources.toml"]
managed = true

4
romm/README.md Normal file
View file

@ -0,0 +1,4 @@
# Compose file for [template]
## Services
## Environment Variables
- EXAMPLE_VAR - Description

77
romm/compose.yaml Normal file
View file

@ -0,0 +1,77 @@
services:
romm:
image: rommapp/romm:latest
container_name: romm
restart: unless-stopped
environment:
- DB_HOST=romm_db
- DB_NAME=romm # Should match MARIADB_DATABASE in mariadb
- DB_USER=romm # Should match MARIADB_USER in mariadb
- DB_PASSWD=${MARIADB_PASSWORD} # Should match MARIADB_PASSWORD in mariadb
- ROMM_AUTH_SECRET_KEY=${ROMM_AUTH_SECRET_KEY} # Generate a key with `openssl rand -hex 32`
- OIDC_ENABLED=true
- OIDC_PROVIDER=authentik
- OIDC_CLIENT_ID=${OIDC_CLIENT_ID}
- OIDC_CLIENT_SECRET=${OIDC_CLIENT_SECRET}
- OIDC_REDIRECT_URI=https://games.fern.garden/api/oauth/openid
- OIDC_SERVER_APPLICATION_URL=https://auth.fern.garden/application/o/romm/
- MOBYGAMES_API_KEY=${MOBYGAMES_API_KEY}
- IGDB_CLIENT_ID=${IGDB_CLIENT_ID} # Generate an ID and SECRET in IGDB
- IGDB_CLIENT_SECRET=${IGDB_CLIENT_SECRET} # https://api-docs.igdb.com/#account-creation
- SCREENSCRAPER_USER=mondas # Use your ScreenScraper username and password
- SCREENSCRAPER_PASSWORD=${SCREENSCRAPER_PASSWORD} # https://docs.romm.app/latest/Getting-Started/Metadata-Providers/#screenscraper
- STEAMGRIDDB_API_KEY=${STEAMGRIDDB_API_KEY} # https://github.com/rommapp/romm/wiki/Metadata-Providers#steamgriddb
volumes:
- romm_resources:/romm/resources # Resources fetched from IGDB (covers, screenshots, etc.)
- romm_redis:/redis-data # Cached data for background tasks
- romm_assets:/romm/assets # Uploaded saves, states, etc.
- romm_config:/romm/config # Path where config.yml is stored
- /media/media/romm:/romm/library/roms:ro # Your game library. Check https://github.com/rommapp/romm?tab=readme-ov-file#folder-structure for more details.
depends_on:
romm_db:
condition: service_healthy
restart: true
networks:
- default
- proxy
labels:
caddy: games.fern.garden
caddy.reverse_proxy: '{{upstreams 8080}}'
romm_db:
image: mariadb:latest
container_name: romm_db
restart: unless-stopped
environment:
- MARIADB_ROOT_PASSWORD=${MARIADB_ROOT_PASSWORD} # Use a unique, secure password
- MARIADB_DATABASE=romm
- MARIADB_USER=romm
- MARIADB_PASSWORD=${MARIADB_PASSWORD}
volumes:
- romm_db:/var/lib/mysql
networks:
- default
healthcheck:
test: [CMD, healthcheck.sh, --connect, --innodb_initialized]
start_period: 30s
start_interval: 10s
interval: 10s
timeout: 5s
retries: 5
networks:
default:
proxy:
external: true
volumes:
romm_db:
name: romm_db
romm_resources:
name: romm_resources
romm_redis:
name: romm_redis
romm_assets:
name: romm_assets
romm_config:
name: romm_config

4
slskd/README.md Normal file
View file

@ -0,0 +1,4 @@
# Compose file for slskd
## Environment Variables
- SLSKD_PASSWORD - slskd user password
- SLSKD_SLSK_PASSWORD - soulseek user password

39
slskd/compose.yaml Normal file
View file

@ -0,0 +1,39 @@
services:
slskd:
image: slskd/slskd:latest
container_name: slskd
networks:
- default
- proxy
- media
user: 1000:1800
ports:
- 50300:50300
environment:
- SLSKD_REMOTE_CONFIGURATION=true
- SLSKD_SHARED_DIR=/media/media/lidarr
- SLSKD_DOWNLOADS_DIR=/media/downloads/slskd/downloads
- SLSKD_INCOMPLETE_DIR=/media/downloads/slskd/incomplete
- SLSKD_USERNAME=fern
- SLSKD_PASSWORD=${SLSKD_PASSWORD}
- SLSKD_SLSK_USERNAME=MtQueerie
- SLSKD_SLSK_PASSWORD=${SLSKD_SLSK_PASSWORD}
volumes:
- slskd_data:/app
- /media:/media
restart: unless-stopped
labels:
caddy: slskd.ferngarden.net
caddy.import: internal
caddy.reverse_proxy: "{{upstreams 5030}}"
networks:
default:
proxy:
external: true
media:
external: true
volumes:
slskd_data:
name: slskd_data

1
stash/README.md Normal file
View file

@ -0,0 +1 @@
# Compose file for stash

46
stash/compose.yaml Normal file
View file

@ -0,0 +1,46 @@
services:
stash:
image: stashapp/stash:latest
container_name: stash
networks:
- default
- proxy
restart: unless-stopped
environment:
- STASH_STASH=/data/
- STASH_GENERATED=/generated/
- STASH_METADATA=/metadata/
- STASH_CACHE=/cache/
- STASH_BLOBS=/blobs/
- STASH_PORT=9999
volumes:
- /etc/localtime:/etc/localtime:ro
- /media/downloads/porn:/data:ro
- stash_config:/root/.stash
- stash_metadata:/metadata
- stash_cache:/cache
- stash_blobs:/blobs
- stash_generated:/generated
labels:
caddy: stash.ferngarden.net
caddy.1_import: internal
caddy.2_import: authentik
networks:
default:
proxy:
external: true
media:
external: true
volumes:
stash_config:
name: stash_config
stash_metadata:
name: stash_metadata
stash_cache:
name: stash_cache
stash_blobs:
name: stash_blobs
stash_generated:
name: stash_generated

25
stirling-pdf/compose.yaml Normal file
View file

@ -0,0 +1,25 @@
services:
stirling-pdf:
image: docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest
container_name: stirling-pdf
volumes:
- /mnt/docker/stirling-pdf/trainingData:/usr/share/tessdata # Required for extra OCR languages
- /mnt/docker/stirling-pdf/extraConfigs:/configs
- /mnt/docker/stirling-pdf/customFiles:/customFiles/
- /mnt/docker/stirling-pdf/logs:/logs/
- /mnt/docker/stirling-pdf/pipeline:/pipeline/
environment:
- DOCKER_ENABLE_SECURITY=false
- LANGS=en_GB
networks:
- default
- proxy
labels:
caddy: pdf.ferngarden.net
caddy.import: internal
caddy.reverse_proxy: '{{ upstreams 8080 }}'
networks:
default:
proxy:
external: true

1
synapse/README.md Normal file
View file

@ -0,0 +1 @@
# Compose file for Synapse

54
synapse/compose.yaml Normal file
View file

@ -0,0 +1,54 @@
services:
synapse:
image: docker.io/matrixdotorg/synapse:latest
container_name: synapse
restart: unless-stopped
networks:
- default
- proxy
environment:
- SYNAPSE_CONFIG_PATH=/data/homeserver.yaml
volumes:
- synapse_data:/data
depends_on:
- synapse_db
labels:
caddy_0: mx.fern.garden
caddy_0.1_reverse_proxy: reverse_proxy /_matrix/* synapse:8008
caddy_0.2_reverse_proxy: reverse_proxy /_synapse/client/* synapse:8008
caddy_1: matrix.fern.garden
caddy_1.handle.1_encode: zstd gzip
caddy_1.handle.2_reverse_proxy: matrix-traefik:8080
caddy_1.handle.2_reverse_proxy.1_header_up: X-Forwarded-Port {http.request.port}
caddy_1.handle.2_reverse_proxy.2_header_up: X-Forwarded-TlsProto {tls_protocol}
caddy_1.handle.2_reverse_proxy.3_header_up: X-Forwarded-TlsCipher {tls_cipher}
caddy_1.handle.2_reverse_proxy.4_header_up: X-Forwarded-HttpsProto {proto}
caddy_2: matrix.fern.garden:8448
caddy_2.handle.1_encode: zstd gzip
caddy_2.handle.2_reverse_proxy: matrix-traefik:8448
caddy_2.handle.2_reverse_proxy.1_header_up: X-Forwarded-Port {http.request.port}
caddy_2.handle.2_reverse_proxy.2_header_up: X-Forwarded-TlsProto {tls_protocol}
caddy_2.handle.2_reverse_proxy.3_header_up: X-Forwarded-TlsCipher {tls_cipher}
caddy_2.handle.2_reverse_proxy.4_header_up: X-Forwarded-HttpsProto {proto}
synapse_db:
image: docker.io/postgres:16-alpine
container_name: synapse_db
networks:
- default
restart: unless-stopped
volumes:
- synapse_db:/var/lib/postgresql/data
networks:
default:
proxy:
external: true
volumes:
synapse_data:
name: synapse_data
synapse_db:
name: synapse_db

3
vaultwarden/README.md Normal file
View file

@ -0,0 +1,3 @@
# Compose file for Vaultwarden
## Environment Variables
- SMTP_PASSWORD - password for SMTP server

31
vaultwarden/compose.yaml Normal file
View file

@ -0,0 +1,31 @@
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
networks:
- default
- proxy
restart: unless-stopped
environment:
- DOMAIN=https://vault.ferngarden.net
- SMTP_HOST=mail.ferngarden.net
- SMTP_PORT=587
- SMTP_SECURITY=starttls
- SMTP_FROM=Vaultwarden <ornithologist@ferngarden.net>
- SMTP_USERNAME=ornithologist@ferngarden.net
- SMTP_PASSWORD=${SMTP_PASSWORD}
volumes:
- vaultwarden_data:/data
labels:
caddy: vault.ferngarden.net
caddy.import: internal
caddy.reverse_proxy: "{{upstreams 80}}"
networks:
default:
proxy:
external: true
volumes:
vaultwarden_data:
name: vaultwarden_data

1
wallos/README.md Normal file
View file

@ -0,0 +1 @@
# Compose file for wallos

26
wallos/compose.yaml Normal file
View file

@ -0,0 +1,26 @@
services:
wallos:
image: bellamy/wallos:latest
container_name: wallos
restart: unless-stopped
networks:
- default
- proxy
volumes:
- wallos_db:/var/www/html/db
- wallos_logos:/var/www/html/images/uploads/logos
labels:
caddy: subscriptions.ferngarden.net
caddy.import: internal
caddy.reverse_proxy: "authentik_proxy:9000"
networks:
default:
proxy:
external: true
volumes:
wallos_db:
name: wallos_db
wallos_logos:
name: wallos_logos