commit 6be7c81137b4fada1efe76883f518e759dbd75f6 Author: Marko Korhonen Date: Sat Apr 8 13:52:03 2023 +0300 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..934c1fb --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*/.env diff --git a/authentik/docker-compose.toml b/authentik/docker-compose.toml new file mode 100644 index 0000000..24904d9 --- /dev/null +++ b/authentik/docker-compose.toml @@ -0,0 +1,71 @@ +[services.redis] +image = "redis:alpine" +container_name = "authentik-redis" +networks = ["authentik"] +restart = "unless-stopped" +volumes = ["/docker/authentik/redis:/data"] + +[services.redis.healthcheck] +test = ["CMD-SHELL", "redis-cli ping | grep PONG"] +start_period = "20s" +interval = "30s" +retries = 5 +timeout = "3s" + +[services.server] +image = "ghcr.io/goauthentik/server" +container_name = "authentik" +restart = "unless-stopped" +command = "server" +volumes = [ + "/docker/authentik/media:/media", + "/docker/authentik/custom-templates:/templates", + "/docker/authentik/geoip:/geoip", +] +env_file = [".env"] +networks = ["authentik", "postgres", "proxy"] + +[services.worker] +image = "ghcr.io/goauthentik/server" +container_name = "authentik-worker" +restart = "unless-stopped" +command = "worker" +user = "root" +volumes = [ + "/docker/authentik/backups:/backups", + "/docker/authentik/custom-templates:/templates", + "/docker/authentik/geoip:/geoip", + "/docker/authentik/media:/media", + "/var/run/docker.sock:/var/run/docker.sock", +] +env_file = [".env"] +networks = ["authentik", "postgres"] + +[services.geoipupdate] +image = "maxmindinc/geoipupdate" +container_name = "authentik-geoipupdate" +restart = "unless-stopped" +networks = ["authentik"] +volumes = ["/docker/authentik/geoip:/usr/share/GeoIP"] +env_file = [".env"] + +[services.geoipupdate.environment] +GEOIPUPDATE_EDITION_IDS = "GeoLite2-City" +GEOIPUPDATE_FREQUENCY = "8" + +[services.whoami-test] +image = "traefik/whoami" +container_name = "whoami-test" +restart = "unless-stopped" +security_opt = ["no-new-privileges:true"] +networks = ["proxy"] +environment = ["TZ"] + +[networks.authentik] +external = true + +[networks.postgres] +external = true + +[networks.proxy] +external = true diff --git a/caddy/Caddyfile b/caddy/Caddyfile new file mode 100644 index 0000000..716ea76 --- /dev/null +++ b/caddy/Caddyfile @@ -0,0 +1,137 @@ +korhonen.cc, *.korhonen.cc { + tls {$CLOUDFLARE_EMAIL} { + dns cloudflare {$CLOUDFLARE_API_TOKEN} + resolvers 1.1.1.1 + } + + encode zstd gzip + + header { + Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" + } + + @homepage-redir host www.korhonen.cc + handle @homepage-redir { + redir https://korhonen.cc + } + + @homepage host korhonen.cc + handle @homepage { + root * /var/www/korhonen.cc + file_server + } + + @wkd host openpgpkey.korhonen.cc + handle @wkd { + root * /var/www/wkd + file_server browse + } + + @index host index.korhonen.cc + handle @index { + root * /var/www/index.korhonen.cc + file_server browse + } + + @home-assistant host home.korhonen.cc + handle @home-assistant { + reverse_proxy home-assistant:8123 + } + + @authentik host sso.korhonen.cc + handle @authentik { + reverse_proxy authentik:9000 + } + + @forgejo host git.korhonen.cc + handle @forgejo { + reverse_proxy forgejo:3000 + } + + @woodpecker host ci.korhonen.cc + handle @woodpecker { + reverse_proxy woodpecker:8000 + } + + @searx host search.korhonen.cc + handle @searx { + reverse_proxy searx:8080 + } + + @freshrss host rss.korhonen.cc + handle @freshrss { + reverse_proxy freshrss + } + + @jellyfin host jellyfin.korhonen.cc + handle @jellyfin { + reverse_proxy jellyfin:8096 + } + + @misskey host social.korhonen.cc + handle @misskey { + reverse_proxy misskey:3000 + } + + @pihole host pihole.korhonen.cc + handle @pihole { + reverse_proxy pihole + } + + @umami host umami.korhonen.cc + handle @umami { + reverse_proxy umami:3000 + } + + @nextcloud host cloud.korhonen.cc + handle @nextcloud { + # .htaccess / data / config / ... shouldn't be accessible from outside + @forbidden { + path /.htaccess + path /data/* + path /config/* + path /db_structure + path /.xml + path /README + path /3rdparty/* + path /lib/* + path /templates/* + path /occ + path /console.php + } + handle @forbidden { + respond 404 + } + + redir /.well-known/carddav /remote.php/dav 301 + redir /.well-known/caldav /remote.php/dav 301 + + root * /var/www/nextcloud + php_fastcgi nextcloud:9000 { + root /var/www/html + # Tells nextcloud to remove /index.php from URLs in links + env front_controller_active true + } + file_server + } + + @tvheadend host tvheadend.korhonen.cc + handle @tvheadend { + reverse_proxy tvheadend:9981 + } + + @collabora host collabora.korhonen.cc + handle @collabora { + reverse_proxy collabora:9980 + } + + @grafana host grafana.korhonen.cc + handle @grafana { + reverse_proxy grafana:3000 + } + + # Fallback for unhandled domains + handle { + redir https://korhonen.cc/404.html 301 + } +} diff --git a/caddy/docker-compose.toml b/caddy/docker-compose.toml new file mode 100644 index 0000000..7a51f6f --- /dev/null +++ b/caddy/docker-compose.toml @@ -0,0 +1,20 @@ +[services.caddy] +image = "slothcroissant/caddy-cloudflaredns" +container_name = "caddy" +restart = "unless-stopped" +user = "82:82" +ports = ["80:80", "443:443/tcp", "443:443/udp"] +networks = ["proxy"] +volumes = [ + "/docker/caddy/data:/data", + "/docker/caddy/config:/config", + "/docker/nextcloud:/var/www/nextcloud", + "/var/www/korhonen.cc:/var/www/korhonen.cc", + "/var/www/wkd:/var/www/wkd", + "/var/www/index.korhonen.cc:/var/www/index.korhonen.cc", + "./Caddyfile:/etc/caddy/Caddyfile", +] +environment = ["CLOUDFLARE_EMAIL", "CLOUDFLARE_API_TOKEN", "ACME_AGREE=true"] + +[networks.proxy] +external = true diff --git a/ddns/docker-compose.toml b/ddns/docker-compose.toml new file mode 100644 index 0000000..7bf009e --- /dev/null +++ b/ddns/docker-compose.toml @@ -0,0 +1,8 @@ +[services.cloudflare-ddns] +image = "timothyjmiller/cloudflare-ddns" +container_name = "cloudflare-ddns" +security_opt = ["no-new-privileges:true"] +network_mode = "host" +environment = ["PUID=1000", "PGID=1000"] +volumes = ["/docker/ddns/config.json:/config.json"] +restart = "unless-stopped" diff --git a/forgejo/docker-compose.toml b/forgejo/docker-compose.toml new file mode 100644 index 0000000..a6dc63d --- /dev/null +++ b/forgejo/docker-compose.toml @@ -0,0 +1,14 @@ +[services.forgejo] +image = "git.korhonen.cc/functionalhacker/forgejo-asciidoc" +container_name = "forgejo" +environment = ["TZ=Europe/Helsinki", "USER_UID=1000", "USER_GID=1000"] +restart = "unless-stopped" +networks = ["postgres", "proxy"] +ports = ["22:22"] +volumes = ["/docker/forgejo:/data", "/etc/localtime:/etc/localtime:ro"] + +[networks.postgres] +external = true + +[networks.proxy] +external = true diff --git a/freshrss/docker-compose.toml b/freshrss/docker-compose.toml new file mode 100644 index 0000000..cfd76b9 --- /dev/null +++ b/freshrss/docker-compose.toml @@ -0,0 +1,19 @@ +[services.freshrss] +image = "linuxserver/freshrss" +container_name = "freshrss" +restart = "unless-stopped" +networks = ["freshrss", "postgres", "proxy"] +environment = ["PUID=1000", "PGID=985", "TZ=Europe/Helsinki"] +volumes = [ + "/docker/freshrss/freshrss:/config", + "/etc/localtime:/etc/localtime:ro", +] + +[networks.freshrss] +external = false + +[networks.postgres] +external = true + +[networks.proxy] +external = true diff --git a/homeautomation/docker-compose.toml b/homeautomation/docker-compose.toml new file mode 100644 index 0000000..6f1eac5 --- /dev/null +++ b/homeautomation/docker-compose.toml @@ -0,0 +1,56 @@ +[services.home-assistant] +container_name = "home-assistant" +image = "homeassistant/home-assistant" +environment = ["TZ=Europe/Helsinki"] +devices = ["/dev/ttyACM0"] +volumes = [ + "/docker/homeautomation/home-assistant:/config", + "/etc/localtime:/etc/localtime:ro", +] +restart = "unless-stopped" +networks = ["homeautomation", "postgres", "proxy"] +ports = ["8123:8123", "8300:8300"] +extra_hosts = ["host.docker.internal:host-gateway"] +depends_on = ["mosquitto"] + +[services.esphome] +container_name = "esphome" +image = "esphome/esphome" +volumes = ["/docker/homeautomation/esphome:/config"] +restart = "unless-stopped" +network_mode = "host" + +[services.mosquitto] +container_name = "mosquitto" +image = "eclipse-mosquitto" +environment = ["TZ=Europe/Helsinki"] +ports = ["1883:1883"] +networks = ["homeautomation"] +volumes = [ + "/docker/homeautomation/mosquitto:/mosquitto", + "/etc/localtime:/etc/localtime:ro", +] +restart = "unless-stopped" + +[services.rhasspy] +container_name = "rhasspy" +image = "rhasspy/rhasspy" +command = "--profile en --user-profiles /profiles" +volumes = ["/docker/homeautomation/rhasspy:/profiles"] +environment = ["TZ=Europe/Helsinki"] +ports = ["12101:12101"] +networks = ["homeautomation"] +restart = "unless-stopped" +depends_on = ["home-assistant"] +devices = ["/dev/snd:/dev/snd"] + +[networks] + +[networks.homeautomation] +external = false + +[networks.postgres] +external = true + +[networks.proxy] +external = true diff --git a/jellyfin/docker-compose.toml b/jellyfin/docker-compose.toml new file mode 100644 index 0000000..f69335b --- /dev/null +++ b/jellyfin/docker-compose.toml @@ -0,0 +1,23 @@ +[services.jellyfin] +image = "jellyfin/jellyfin" +container_name = "jellyfin" +environment = ["TZ=Europe/Helsinki"] +networks = ["proxy", "authentik"] +restart = "unless-stopped" +volumes = [ + "/docker/jellyfin/config:/config", + "/docker/jellyfin/cache:/cache", + "/mnt/Storage/Media:/media", + "/mnt/Storage/Nextcloud/FunctionalHacker/files/Media/Music:/media/Music", + "/etc/localtime:/etc/localtime:ro", +] +devices = [ + "/dev/dri/renderD128:/dev/dri/renderD128", + "/dev/dri/card0:/dev/dri/card0", +] + +[networks.proxy] +external = true + +[networks.authentik] +external = true diff --git a/misskey/docker-compose.toml b/misskey/docker-compose.toml new file mode 100644 index 0000000..01ca5b2 --- /dev/null +++ b/misskey/docker-compose.toml @@ -0,0 +1,44 @@ +[services.misskey] +image = "misskey/misskey" +container_name = "misskey" +restart = "unless-stopped" +depends_on = ["redis"] +ports = ["3082:3000"] +networks = ["misskey", "proxy", "postgres"] +volumes = [ + "/docker/misskey/files:/misskey/files", + "/docker/misskey/config:/misskey/.config:ro", +] + +[services.elasticsearch] +image = "docker.elastic.co/elasticsearch/elasticsearch:7.17.8" +container_name = "misskey-elasticsearch" +restart = "unless-stopped" +volumes = ["/docker/misskey/elasticsearch/:/usr/share/elasticsearch/data"] +networks = ["misskey"] +environment = [ + "cluster.name=misskey-es-cluster", + "node.name=misskey-node", + "discovery.type=single-node", + "bootstrap.memory_lock=true", + "ES_JAVA_OPTS=-Xms200m -Xmx200m", +] +[services.elasticsearch.ulimits.memlock] +soft = -1 +hard = -1 + +[services.redis] +image = "redis" +container_name = "redis-misskey" +restart = "unless-stopped" +networks = ["misskey"] +volumes = ["/docker/misskey/redis:/data"] + +[networks.misskey] +internal = true + +[networks.proxy] +external = true + +[networks.postgres] +external = true diff --git a/nextcloud/docker-compose.toml b/nextcloud/docker-compose.toml new file mode 100644 index 0000000..1bf978c --- /dev/null +++ b/nextcloud/docker-compose.toml @@ -0,0 +1,80 @@ +[services.nextcloud] +image = "nextcloud:fpm-alpine" +container_name = "nextcloud" +restart = "unless-stopped" +user = "82:82" +networks = ["nextcloud", "postgres", "proxy"] +volumes = [ + "/docker/nextcloud:/var/www/html:z", + "/mnt/Storage/Nextcloud:/var/www/html/data", + "/etc/localtime:/etc/localtime:ro", +] +environment = [ + "TZ=Europe/Helsinki", + "REDIS_HOST=redis", + "REDIS_HOST_PASSWORD=123", + "TRUSTED_PROXIES=traefik", + "NEXTCLOUD_TRUSTED_DOMAINS=cloud.korhonen.cc", + "OVERWRITEHOST=cloud.korhonen.cc", + "OVERWRITEPROTOCOL=https", +] +depends_on = ["redis"] +labels = [ + "ofelia.enabled=true", + "ofelia.job-exec.nextcloud.schedule=0 */5 * * * *", + "ofelia.job-exec.nextcloud.command=php /var/www/html/cron.php", + "ofelia.job-exec.nextcloud.user=www-data", + "ofelia.smtp-host=${SMTP_HOST}", + "ofelia.smtp-port=${SMTP_PORT}", + "ofelia.smtp-user=${SMTP_USER}", + "ofelia.smtp-password=${SMTP_PASSWORD}", + "ofelia.email-to=${EMAIL_TO}", + "ofelia.email-from=${EMAIL_FROM}", + "ofelia.mail-only-on-error", +] + +[services.redis] +image = "redis:alpine" +container_name = "redis-nextcloud" +networks = ["nextcloud"] +restart = "unless-stopped" +command = "redis-server --requirepass 123" + +[services.coturn] +image = "instrumentisto/coturn" +container_name = "coturn" +restart = "unless-stopped" +env_file = ".env" +ports = ["3478:3478/tcp", "3478:3478/udp"] +networks = ["nextcloud"] +command = [ + "-n", + "--log-file=stdout", + "--min-port=49160", + "--max-port=49200", + "--realm=cloud.korhonen.cc", + "--use-auth-secret", + "--static-auth-secret=${STATIC_AUTH_SECRET}", +] + +[services.collabora] +image = "collabora/code" +container_name = "collabora" +restart = "unless-stopped" +env_file = ".env" +environment = [ + "username=${COLLABORA_USERNAME}", + "password=${COLLABORA_PASSWORD}", + "domain=cloud.korhonen.cc", + 'extra_params=--o:ssl.enable=false --o:ssl.termination=true', +] +networks = ["proxy"] + +[networks.nextcloud] +external = false + +[networks.postgres] +external = true + +[networks.proxy] +external = true diff --git a/ofelia/docker-compose.toml b/ofelia/docker-compose.toml new file mode 100644 index 0000000..e9e5ea0 --- /dev/null +++ b/ofelia/docker-compose.toml @@ -0,0 +1,9 @@ +[services.ofelia] +image = "mcuadros/ofelia" +container_name = "ofelia" +restart = "unless-stopped" +volumes = [ + "/etc/localtime:/etc/localtime:ro", + "/var/run/docker.sock:/var/run/docker.sock:ro", +] +command = "daemon --docker" diff --git a/pihole/docker-compose.toml b/pihole/docker-compose.toml new file mode 100644 index 0000000..9f32819 --- /dev/null +++ b/pihole/docker-compose.toml @@ -0,0 +1,23 @@ +[services] + +[services.pihole] +container_name = "pihole" +image = "pihole/pihole" +ports = ["53:53/tcp", "53:53/udp", "67:67/udp", "8069:80/tcp"] +networks = ["proxy"] +volumes = [ + "/docker/pihole/pihole:/etc/pihole/", + "/docker/pihole/dnsmasq:/etc/dnsmasq.d/", +] +dns = ["127.0.0.1", "1.1.1.1"] +cap_add = ["NET_ADMIN"] +restart = "unless-stopped" + +[services.pihole.environment] +TZ = "Europe/Helsinki" +WEBPASSWORD = "${WEBPASSWORD}" + +[networks] + +[networks.proxy] +external = true diff --git a/postgres/docker-compose.toml b/postgres/docker-compose.toml new file mode 100644 index 0000000..e8a9ec8 --- /dev/null +++ b/postgres/docker-compose.toml @@ -0,0 +1,18 @@ +[services] + +[services.postgres] +container_name = "postgres" +image = "postgres:15" +environment = ["TZ=Europe/Helsinki", "POSTGRES_PASSWORD=12345"] +ports = ["5432:5432"] +networks = ["postgres"] +volumes = [ + "/docker/postgres:/var/lib/postgresql/data", + "/etc/localtime:/etc/localtime:ro", +] +restart = "unless-stopped" + +[networks] + +[networks.postgres] +external = true diff --git a/searx/docker-compose.toml b/searx/docker-compose.toml new file mode 100644 index 0000000..f2c1dd7 --- /dev/null +++ b/searx/docker-compose.toml @@ -0,0 +1,34 @@ +[services.searx] +container_name = "searx" +image = "searxng/searxng" +restart = "unless-stopped" +networks = ["searx", "proxy"] +volumes = [ + "/docker/searx:/etc/searxng", + #"/docker/searx/logo.png:/usr/local/searxng/searx/static/themes/simple/img/searxng.png:ro" +] +environment = ["SEARXNG_BASE_URL=https://search.korhonen.cc/"] +cap_drop = ["ALL"] +cap_add = ["CHOWN", "SETGID", "SETUID", "DAC_OVERRIDE"] + +[services.searx.logging] +driver = "json-file" + +[services.searx.logging.options] +max-size = "1m" +max-file = "1" + +[services.redis] +container_name = "redis-searx" +image = "redis:alpine" +command = "redis-server --save \"\" --appendonly \"no\"" +networks = ["searx"] +tmpfs = ["/var/lib/redis"] +cap_drop = ["ALL"] +cap_add = ["SETGID", "SETUID", "DAC_OVERRIDE"] + +[networks.searx.ipam] +driver = "default" + +[networks.proxy] +external = true diff --git a/stats/docker-compose.toml b/stats/docker-compose.toml new file mode 100644 index 0000000..ff0e084 --- /dev/null +++ b/stats/docker-compose.toml @@ -0,0 +1,27 @@ +[services.grafana] +image = "grafana/grafana" +container_name = "grafana" +volumes = ["/docker/stats/grafana:/var/lib/grafana"] +networks = ["stats", "proxy"] +user = "1000:984" +env_file = [".env"] +environment = [ + "GF_AUTH_GENERIC_OAUTH_CLIENT_ID", + "GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET", + "GF_AUTH_GENERIC_OAUTH_ENABLED=true", + "GF_AUTH_GENERIC_OAUTH_NAME=authentik", + "GF_AUTH_GENERIC_OAUTH_SCOPES=openid profile email", + "GF_AUTH_GENERIC_OAUTH_AUTH_URL=https://sso.korhonen.cc/application/o/authorize/", + "GF_AUTH_GENERIC_OAUTH_TOKEN_URL=https://sso.korhonen.cc/application/o/token/", + "GF_AUTH_GENERIC_OAUTH_API_URL=https://sso.korhonen.cc/application/o/userinfo/", + "GF_AUTH_SIGNOUT_REDIRECT_URL=https://sso.korhonen.cc/application/o/grafana/end-session/", + "GF_AUTH_OAUTH_AUTO_LOGIN=true", + "GF_SERVER_ROOT_URL=https://grafana.korhonen.cc", + "GF_AUTH_GENERIC_OAUTH_ROLE_ATTRIBUTE_PATH=contains(groups[*], 'Administrators') && 'Admin' || 'Viewer'", +] + +[networks.stats] +external = false + +[networks.proxy] +external = true diff --git a/tvheadend/docker-compose.toml b/tvheadend/docker-compose.toml new file mode 100644 index 0000000..cdbff58 --- /dev/null +++ b/tvheadend/docker-compose.toml @@ -0,0 +1,17 @@ +[services.tvheadend] +image = "linuxserver/tvheadend" +container_name = "tvheadend" +environment = ["TZ=Europe/Helsinki", "PUID=1000", "PGID=985"] +volumes = [ + "/docker/tvheadend:/config", + "/mnt/Storage/Media/PVR:/recordings", + "/mnt/Storage/picons:/picons", + "/etc/localtime:/etc/localtime:ro", +] +ports = ["9981:9981", "9982:9982"] +devices = ["/dev/dvb:/dev/dvb"] +restart = "unless-stopped" +networks = ["proxy"] + +[networks.proxy] +external = true diff --git a/umami/docker-compose.toml b/umami/docker-compose.toml new file mode 100644 index 0000000..3d5a92d --- /dev/null +++ b/umami/docker-compose.toml @@ -0,0 +1,21 @@ +[services.umami] +image = "ghcr.io/umami-software/umami:postgresql-latest" +container_name = "umami" +restart = "unless-stopped" +networks = ["postgres", "proxy"] +env_file = ".env" + +[services.umami.environment] +DATABASE_URL = "postgresql://umami:${POSTGRES_PASS}@postgres:5432/umami" +HASH_SALT = "${HASH_SALT}" +TRACKER_SCRIPT_NAME = "ua9quuaW" + +[services.umami.logging.options] +max-size = "10m" +max-file = "10" + +[networks.postgres] +external = true + +[networks.proxy] +external = true diff --git a/woodpecker/docker-compose.toml b/woodpecker/docker-compose.toml new file mode 100644 index 0000000..7a4c823 --- /dev/null +++ b/woodpecker/docker-compose.toml @@ -0,0 +1,33 @@ +[services.woodpecker] +image = "woodpeckerci/woodpecker-server" +container_name = "woodpecker" +restart = "unless-stopped" +volumes = ["/docker/woodpecker/:/var/lib/woodpecker/"] +env_file = [".env"] +environment = [ + "WOODPECKER_OPEN=true", + "WOODPECKER_GITEA=true", + "WOODPECKER_GITEA_URL=https://git.korhonen.cc", + "WOODPECKER_GITEA_CLIENT", + "WOODPECKER_GITEA_SECRET", + "WOODPECKER_AGENT_SECRET", + "WOODPECKER_HOST=https://ci.korhonen.cc", + "WOODPECKER_ADMIN=FunctionalHacker", +] +networks = ["proxy", "default"] + +[services.woodpecker-agent] +image = "woodpeckerci/woodpecker-agent" +container_name = "woodpecker-agent" +command = "agent" +restart = "unless-stopped" +depends_on = ["woodpecker"] +volumes = ["/var/run/docker.sock:/var/run/docker.sock"] +env_file = [".env"] +environment = [ + "WOODPECKER_SERVER=woodpecker:9000", + "WOODPECKER_AGENT_SECRET", +] + +[networks.proxy] +external = true