commit a92e665f35a2c043382b4a377c443555c8178d2f Author: Menno van Leeuwen Date: Sat Nov 16 04:43:13 2024 +0100 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..debc63c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +**/data/ +.env diff --git a/arr-stack/docker-compose.yml b/arr-stack/docker-compose.yml new file mode 100644 index 0000000..7e1dcbe --- /dev/null +++ b/arr-stack/docker-compose.yml @@ -0,0 +1,149 @@ +name: arr-stack +services: + radarr: + container_name: radarr + image: lscr.io/linuxserver/radarr:latest + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/Amsterdam + ports: + - 7878:7878 + extra_hosts: + - host.docker.internal:host-gateway + volumes: + - ./data/radarr-config:/config + - /mnt:/storage + restart: "unless-stopped" + networks: + - shared_network + + sonarr: + image: linuxserver/sonarr:latest + container_name: sonarr + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/Amsterdam + volumes: + - ./data/sonarr-config:/config + - /mnt:/storage + ports: + - 8989:8989 + extra_hosts: + - host.docker.internal:host-gateway + restart: unless-stopped + networks: + - shared_network + + lidarr: + image: linuxserver/lidarr:latest + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/Amsterdam + ports: + - 8686:8686 + extra_hosts: + - host.docker.internal:host-gateway + volumes: + - ./data/lidarr-config:/config + - /mnt:/storage + restart: unless-stopped + networks: + - shared_network + + whisparr: + image: ghcr.io/hotio/whisparr:latest + environment: + - TZ=Europe/Amsterdam + ports: + - 8386:6969 + extra_hosts: + - host.docker.internal:host-gateway + volumes: + - ./data/whisparr-config:/config + - /mnt:/storage + restart: unless-stopped + networks: + - shared_network + + prowlarr: + container_name: prowlarr + image: linuxserver/prowlarr:latest + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/Amsterdam + volumes: + - ./data/prowlarr-config:/config + extra_hosts: + - host.docker.internal:host-gateway + ports: + - 9696:9696 + restart: unless-stopped + networks: + - shared_network + + flaresolverr: + image: ghcr.io/flaresolverr/flaresolverr:latest + container_name: flaresolverr + environment: + - LOG_LEVEL=${LOG_LEVEL:-info} + - LOG_HTML=${LOG_HTML:-false} + - CAPTCHA_SOLVER=${CAPTCHA_SOLVER:-none} + - TZ=Europe/Amsterdam + ports: + - "8191:8191" + extra_hosts: + - host.docker.internal:host-gateway + restart: unless-stopped + networks: + - shared_network + + jellyfin: + image: lscr.io/linuxserver/jellyfin:latest + container_name: jellyfin + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/Amsterdam + - JELLYFIN_PublishedServerUrl=https://jellyfin.vleeuwen.me + volumes: + - ./data/jellyfin-config:/config + - /mnt:/mnt + ports: + - 8096:8096 + - 8920:8920 + - 7359:7359/udp + - 1900:1900/udp + restart: unless-stopped + group_add: + - "992" + - "44" + devices: + - /dev/dri/renderD128:/dev/dri/renderD128 + networks: + - shared_network + + overseerr: + image: lscr.io/linuxserver/overseerr:latest + container_name: overseerr + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/Amsterdam + volumes: + - ./data/overseerr-config:/config + ports: + - 5555:5055 + extra_hosts: + - host.docker.internal:host-gateway + restart: unless-stopped + networks: + - shared_network + +networks: + shared_network: + external: true + name: shared_network \ No newline at end of file diff --git a/codeserver/docker-compose.yml b/codeserver/docker-compose.yml new file mode 100644 index 0000000..084207c --- /dev/null +++ b/codeserver/docker-compose.yml @@ -0,0 +1,18 @@ +name: codeserver +services: + server: + image: lscr.io/linuxserver/code-server:latest + container_name: code-server + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/Amsterdam + - HASHED_PASSWORD= + - SUDO_PASSWORD_HASH= + - DEFAULT_WORKSPACE=/config/workspace + volumes: + - ./data:/config + - /mnt:/config/workspace + ports: + - 8443:8443 + restart: unless-stopped diff --git a/duplicati/docker-compose.yml b/duplicati/docker-compose.yml new file mode 100644 index 0000000..3db4b87 --- /dev/null +++ b/duplicati/docker-compose.yml @@ -0,0 +1,25 @@ +name: duplicati +services: + app: + image: lscr.io/linuxserver/duplicati:latest + environment: + - PUID=1 + - PGID=1 + - TZ=Europe/Amsterdam + - CLI_ARGS= + volumes: + - /mnt/services/duplicati/data:/config + - /mnt:/mnt + ports: + - 8200:8200 + extra_hosts: + - host.docker.internal:host-gateway + restart: unless-stopped + + notifications: + image: ghcr.io/vleeuwenmenno/duplicati-discord-notification:main + ports: + - 5334:5000 + extra_hosts: + - host.docker.internal:host-gateway + restart: unless-stopped diff --git a/factorio/docker-compose.yml b/factorio/docker-compose.yml new file mode 100644 index 0000000..ccf073e --- /dev/null +++ b/factorio/docker-compose.yml @@ -0,0 +1,20 @@ +name: factorio +services: + server-manager: + image: "ofsm/ofsm:latest" + container_name: "factorio-server-manager" + restart: "unless-stopped" + environment: + - PUID=1000 + - PGID=1000 + - "FACTORIO_VERSION=stable" + - "RCON_PASS=458fc84534" + ports: + - "5080:80" + - "34197:34197/udp" + volumes: + - "/mnt/services/factorio/data/fsm-data:/opt/fsm-data" + - "/mnt/services/factorio/data/factorio-data/saves:/opt/factorio/saves" + - "/mnt/services/factorio/data/factorio-data/mods:/opt/factorio/mods" + - "/mnt/services/factorio/data/factorio-data/config:/opt/factorio/config" + - "/mnt/services/factorio/data/factorio-data/mod_packs:/opt/fsm/mod_packs" diff --git a/gitea/act-runner-config.yaml b/gitea/act-runner-config.yaml new file mode 100644 index 0000000..648db96 --- /dev/null +++ b/gitea/act-runner-config.yaml @@ -0,0 +1,98 @@ +# Example configuration file, it's safe to copy this as the default config file without any modification. + +# You don't have to copy this file to your instance, +# just run `./act_runner generate-config > config.yaml` to generate a config file. + +log: + # The level of logging, can be trace, debug, info, warn, error, fatal + level: info + +runner: + # Where to store the registration result. + file: .runner + # Execute how many tasks concurrently at the same time. + capacity: 1 + # Extra environment variables to run jobs. + envs: + A_TEST_ENV_NAME_1: a_test_env_value_1 + A_TEST_ENV_NAME_2: a_test_env_value_2 + # Extra environment variables to run jobs from a file. + # It will be ignored if it's empty or the file doesn't exist. + env_file: .env + # The timeout for a job to be finished. + # Please note that the Gitea instance also has a timeout (3h by default) for the job. + # So the job could be stopped by the Gitea instance if it's timeout is shorter than this. + timeout: 3h + # Whether skip verifying the TLS certificate of the Gitea instance. + insecure: false + # The timeout for fetching the job from the Gitea instance. + fetch_timeout: 5s + # The interval for fetching the job from the Gitea instance. + fetch_interval: 2s + # The labels of a runner are used to determine which jobs the runner can run, and how to run them. + # Like: "macos-arm64:host" or "ubuntu-latest:docker://gitea/runner-images:ubuntu-latest" + # Find more images provided by Gitea at https://gitea.com/gitea/runner-images . + # If it's empty when registering, it will ask for inputting labels. + # If it's empty when execute `daemon`, will use labels in `.runner` file. + labels: + - "ubuntu-latest:docker://gitea/runner-images:ubuntu-latest" + - "ubuntu-22.04:docker://gitea/runner-images:ubuntu-22.04" + - "ubuntu-20.04:docker://gitea/runner-images:ubuntu-20.04" + +cache: + # Enable cache server to use actions/cache. + enabled: true + # The directory to store the cache data. + # If it's empty, the cache data will be stored in $HOME/.cache/actcache. + dir: "" + # The host of the cache server. + # It's not for the address to listen, but the address to connect from job containers. + # So 0.0.0.0 is a bad choice, leave it empty to detect automatically. + host: "" + # The port of the cache server. + # 0 means to use a random available port. + port: 0 + # The external cache server URL. Valid only when enable is true. + # If it's specified, act_runner will use this URL as the ACTIONS_CACHE_URL rather than start a server by itself. + # The URL should generally end with "/". + external_server: "" + +container: + # Specifies the network to which the container will connect. + # Could be host, bridge or the name of a custom network. + # If it's empty, act_runner will create a network automatically. + network: "" + # Whether to use privileged mode or not when launching task containers (privileged mode is required for Docker-in-Docker). + privileged: false + # And other options to be used when the container is started (eg, --add-host=my.gitea.url:host-gateway). + options: + # The parent directory of a job's working directory. + # NOTE: There is no need to add the first '/' of the path as act_runner will add it automatically. + # If the path starts with '/', the '/' will be trimmed. + # For example, if the parent directory is /path/to/my/dir, workdir_parent should be path/to/my/dir + # If it's empty, /workspace will be used. + workdir_parent: + # Volumes (including bind mounts) can be mounted to containers. Glob syntax is supported, see https://github.com/gobwas/glob + # You can specify multiple volumes. If the sequence is empty, no volumes can be mounted. + # For example, if you only allow containers to mount the `data` volume and all the json files in `/src`, you should change the config to: + # valid_volumes: + # - data + # - /src/*.json + # If you want to allow any volume, please use the following configuration: + # valid_volumes: + # - '**' + valid_volumes: [] + # overrides the docker client host with the specified one. + # If it's empty, act_runner will find an available docker host automatically. + # If it's "-", act_runner will find an available docker host automatically, but the docker host won't be mounted to the job containers and service containers. + # If it's not empty or "-", the specified docker host will be used. An error will be returned if it doesn't work. + docker_host: "" + # Pull docker image(s) even if already present + force_pull: true + # Rebuild docker image(s) even if already present + force_rebuild: false + +host: + # The parent directory of a job's working directory. + # If it's empty, $HOME/.cache/act/ will be used. + workdir_parent: diff --git a/gitea/docker-compose.yml b/gitea/docker-compose.yml new file mode 100644 index 0000000..ca9de13 --- /dev/null +++ b/gitea/docker-compose.yml @@ -0,0 +1,50 @@ +name: gittea +services: + server: + image: gitea/gitea:latest + restart: always + environment: + - PUID=1000 + - PGID=1000 + volumes: + - /mnt/services/gitea/data/gitea:/data + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + ports: + - "3030:3000" + - "22:22" + networks: + - net + + postgres: + image: postgres:15-alpine + restart: always + environment: + - PUID=1000 + - PGID=1000 + - POSTGRES_USER=gitea + - POSTGRES_PASSWORD=gitea + - POSTGRES_DB=gitea + volumes: + - /mnt/services/gitea/data/postgres:/var/lib/postgresql/data + networks: + - net + + act_runner: + image: gitea/act_runner:latest + volumes: + - ./act-runner-config.yaml:/config.yaml + - /var/run/docker.sock:/var/run/docker.sock + environment: + - PUID=1000 + - PGID=1000 + - GITEA_INSTANCE_URL=https://git.mvl.sh + - GITEA_RUNNER_REGISTRATION_TOKEN=lIlte9POlu7aBanhCh3Xm1SPfohrexyfxqs9Yiqz + - GITEA_RUNNER_NAME=act-worker + - CONFIG_FILE=/config.yaml + restart: always + networks: + - net + +networks: + net: \ No newline at end of file diff --git a/golink/docker-compose.yml b/golink/docker-compose.yml new file mode 100644 index 0000000..74a366e --- /dev/null +++ b/golink/docker-compose.yml @@ -0,0 +1,11 @@ +name: golink +services: + server: + image: ghcr.io/tailscale/golink:main + environment: + - PUID=1000 + - PGID=1000 + - TS_AUTHKEY=${TS_AUTHKEY} + volumes: + - /mnt/services/golink/data:/home/nonroot + restart: "unless-stopped" diff --git a/immich/docker-compose.yml b/immich/docker-compose.yml new file mode 100644 index 0000000..bcbee61 --- /dev/null +++ b/immich/docker-compose.yml @@ -0,0 +1,84 @@ +name: immich +services: + server: + image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release} + #extends: + # file: hwaccel.transcoding.yml + # service: nvenc # set to one of [nvenc, quicksync, rkmpp, vaapi, vaapi-wsl] for accelerated transcoding + volumes: + - ${UPLOAD_LOCATION}:/usr/src/app/upload + - /etc/localtime:/etc/localtime:ro + env_file: + - .env + ports: + - '2283:2283' + depends_on: + - redis + - database + environment: + - PUID=1000 + - PGID=1000 + restart: always + healthcheck: + disable: false + + machine-learning: + # For hardware acceleration, add one of -[armnn, cuda, openvino] to the image tag. + # Example tag: ${IMMICH_VERSION:-release}-cuda + image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}-cuda + #extends: # uncomment this section for hardware acceleration - see https://immich.app/docs/features/ml-hardware-acceleration + # file: hwaccel.ml.yml + # service: cuda # set to one of [armnn, cuda, openvino, openvino-wsl] for accelerated inference - use the `-wsl` version for WSL2 where applicable + volumes: + - model-cache:/cache + env_file: + - .env + restart: always + healthcheck: + disable: false + + redis: + container_name: immich_redis + image: docker.io/redis:6.2-alpine@sha256:2ba50e1ac3a0ea17b736ce9db2b0a9f6f8b85d4c27d5f5accc6a416d8f42c6d5 + healthcheck: + test: redis-cli ping || exit 1 + restart: always + + database: + container_name: immich_postgres + image: docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:90724186f0a3517cf6914295b5ab410db9ce23190a2d9d0b9dd6463e3fa298f0 + environment: + PUID: 1000 + PGID: 1000 + POSTGRES_PASSWORD: ${DB_PASSWORD} + POSTGRES_USER: ${DB_USERNAME} + POSTGRES_DB: ${DB_DATABASE_NAME} + POSTGRES_INITDB_ARGS: '--data-checksums' + volumes: + # Do not edit the next line. If you want to change the database storage location on your system, edit the value of DB_DATA_LOCATION in the .env file + - ${DB_DATA_LOCATION}:/var/lib/postgresql/data + healthcheck: + test: pg_isready --dbname='${DB_DATABASE_NAME}' --username='${DB_USERNAME}' || exit 1; Chksum="$$(psql --dbname='${DB_DATABASE_NAME}' --username='${DB_USERNAME}' --tuples-only --no-align --command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')"; echo "checksum failure count is $$Chksum"; [ "$$Chksum" = '0' ] || exit 1 + interval: 5m + start_interval: 30s + start_period: 5m + command: + [ + 'postgres', + '-c', + 'shared_preload_libraries=vectors.so', + '-c', + 'search_path="$$user", public, vectors', + '-c', + 'logging_collector=on', + '-c', + 'max_wal_size=2GB', + '-c', + 'shared_buffers=512MB', + '-c', + 'wal_compression=on', + ] + restart: always + +volumes: + model-cache: diff --git a/immich/hwaccel.ml.yml b/immich/hwaccel.ml.yml new file mode 100644 index 0000000..34d9483 --- /dev/null +++ b/immich/hwaccel.ml.yml @@ -0,0 +1,21 @@ +# Configurations for hardware-accelerated machine learning + +# If using Unraid or another platform that doesn't allow multiple Compose files, +# you can inline the config for a backend by copying its contents +# into the immich-machine-learning service in the docker-compose.yml file. + +# See https://immich.app/docs/features/ml-hardware-acceleration for info on usage. + +services: + cpu: {} + + cuda: + deploy: + resources: + reservations: + devices: + - driver: nvidia + count: 1 + capabilities: + - gpu + diff --git a/immich/hwaccel.transcoding.yml b/immich/hwaccel.transcoding.yml new file mode 100644 index 0000000..3513352 --- /dev/null +++ b/immich/hwaccel.transcoding.yml @@ -0,0 +1,26 @@ +# Configurations for hardware-accelerated transcoding + +# If using Unraid or another platform that doesn't allow multiple Compose files, +# you can inline the config for a backend by copying its contents +# into the immich-microservices service in the docker-compose.yml file. + +# See https://immich.app/docs/features/hardware-transcoding for more info on using hardware transcoding. + +services: + cpu: {} + + nvenc: + deploy: + resources: + reservations: + devices: + - driver: nvidia + count: 1 + capabilities: + - gpu + - compute + - video + vaapi: + devices: + - /dev/dri:/dev/dri + diff --git a/minecraft/docker-compose.yml b/minecraft/docker-compose.yml new file mode 100644 index 0000000..5dea0ea --- /dev/null +++ b/minecraft/docker-compose.yml @@ -0,0 +1,79 @@ +name: minecraft +services: + upnp: + image: ghcr.io/vleeuwenmenno/auto-upnp:latest + restart: unless-stopped + network_mode: host + environment: + UPNP_DURATION: 86400 # 24 hours in seconds + PORTS: | + [ + {"port": 25565, "protocol": "tcp"}, + {"port": 25565, "protocol": "udp"}, + {"port": 24454, "protocol": "udp"}, + {"port": 3456, "protocol": "tcp"}, + {"port": 19132, "protocol": "udp"} + ] + + paper: + image: itzg/minecraft-server + tty: true + stdin_open: true + ports: + - "25565:25565/tcp" + - "24454:24454/udp" + - "19132:19132/udp" + - "3456:8100/tcp" + environment: + PUID: 1000 + PGID: 1000 + EULA: "TRUE" + TYPE: "paper" + VERSION: 1.21.1 + DIFFICULTY: "hard" + SERVER_NAME: "Paper Mostly Vanilla Server" + MOTD: "Paper Server (Supports 1.20.x and newer!)" + MEMORY: "32G" + MAX_PLAYERS: 32 + VIEW_DISTANCE: 32 + SPAWN_MONSTERS: true + SPAWN_ANIMALS: true + ENFORCE_SECURE_PROFILE: false + + PLUGINS: | + https://cdn.modrinth.com/data/Jrmoreqs/versions/Ch2Vh0XL/AdvancedBackups-spigot-1.21-3.6.3.jar + https://cdn.modrinth.com/data/9eGKb6K1/versions/tA5pALYl/voicechat-bukkit-2.5.25.jar + https://cdn.modrinth.com/data/eBqOQXoA/versions/ndMZChDv/RecoveryTotem-1.0.1.jar + https://cdn.modrinth.com/data/fALzjamp/versions/ytBhnGfO/Chunky-Bukkit-1.4.28.jar + https://cdn.modrinth.com/data/P1OZGk5p/versions/ffAFJrjN/ViaVersion-5.1.1.jar + https://cdn.modrinth.com/data/NpvuJQoq/versions/kwAAl5BS/ViaBackwards-5.1.1.jar + https://cdn.modrinth.com/data/wKkoqHrH/versions/ohEXB7mE/Geyser-Spigot.jar + https://cdn.modrinth.com/data/Vebnzrzj/versions/cfNN7sys/LuckPerms-Bukkit-5.4.145.jar + https://cdn.modrinth.com/data/swbUV1cr/versions/DB0OeC5p/bluemap-5.4-spigot.jar + + OPS: | + StarDebris + + WHITELIST: | + StarDebris + Audi358 + TechnikTake + MsPremium + Barny_8874 + Ricky_2405 + KinderKiller3000 + ScherzkeksMiner + PauBau + QuickWitPhil + Draxonix + Zakomi + skintsoldier122 + Krank4ever + Benjilami + Barny_8847 + Destination456 + xKizu + + restart: unless-stopped + volumes: + - /mnt/services/minecraft/data:/data diff --git a/minecraft/shell.sh b/minecraft/shell.sh new file mode 100755 index 0000000..658875c --- /dev/null +++ b/minecraft/shell.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +docker compose exec paper rcon-cli $@ diff --git a/plex/docker-compose.yml b/plex/docker-compose.yml new file mode 100644 index 0000000..3453fa0 --- /dev/null +++ b/plex/docker-compose.yml @@ -0,0 +1,39 @@ +services: + plex: + image: lscr.io/linuxserver/plex:latest + container_name: plex + network_mode: host + environment: + - PUID=1000 + - PGID=1000 + - VERSION=docker + - PLEX_CLAIM=${PLEX_CLAIM} + - NVIDIA_VISIBLE_DEVICES=all + - NVIDIA_DRIVER_CAPABILITIES=compute,video,utility + volumes: + - /mnt/services/plex/data/plex:/config + - /mnt/movies:/movies + - /mnt/tvshows:/tvshows + - /mnt/music:/music + - /dev/dri/renderD128:/dev/dri/renderD128 + restart: unless-stopped + + tautulli: + image: lscr.io/linuxserver/tautulli:latest + container_name: tautulli + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/Amsterdam + volumes: + - /mnt/services/plex/data/tautulli:/config + ports: + - 8181:8181 + restart: unless-stopped + networks: + - shared_network + +networks: + shared_network: + external: true + name: shared_network \ No newline at end of file diff --git a/proxy/docker-compose.yml b/proxy/docker-compose.yml new file mode 100644 index 0000000..0e179e7 --- /dev/null +++ b/proxy/docker-compose.yml @@ -0,0 +1,11 @@ +services: + nginx-proxy-manager: + image: 'jc21/nginx-proxy-manager:latest' + restart: unless-stopped + cap_add: + - NET_BIND_SERVICE + privileged: true + network_mode: host + volumes: + - /mnt/services/proxy/data:/data + - /mnt/services/proxy/data/letsencrypt:/etc/letsencrypt diff --git a/sabnzbd/docker-compose.yml b/sabnzbd/docker-compose.yml new file mode 100644 index 0000000..815385f --- /dev/null +++ b/sabnzbd/docker-compose.yml @@ -0,0 +1,21 @@ +services: + sabnzbd: + image: lscr.io/linuxserver/sabnzbd:latest + container_name: sabnzbd + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/Amsterdam + volumes: + - /mnt/services/sabnzbd/data:/config + - /mnt:/storage + ports: + - 7788:8080 + restart: unless-stopped + networks: + - shared_network + +networks: + shared_network: + external: true + name: shared_network \ No newline at end of file diff --git a/satisfactory/docker-compose.yml b/satisfactory/docker-compose.yml new file mode 100644 index 0000000..186a7b2 --- /dev/null +++ b/satisfactory/docker-compose.yml @@ -0,0 +1,44 @@ +name: satisfactory +services: + server: + hostname: 'satisfactory-server' + image: 'wolveix/satisfactory-server:latest' + restart: unless-stopped + volumes: + - './data/config:/config' + - './data/certs/live/satisfactory.mvl.sh/fullchain.pem:/config/gamefiles/FactoryGame/Certificates/cert_chain.pem' + - './data/certs/live/satisfactory.mvl.sh/privkey.pem:/config/gamefiles/FactoryGame/Certificates/private_key.pem' + environment: + - MAXPLAYERS=4 + - PGID=1000 + - PUID=1000 + - ROOTLESS=false + - STEAMBETA=false + healthcheck: + test: [ "CMD", "bash", "/healthcheck.sh" ] + interval: 30s + timeout: 10s + retries: 3 + start_period: 120s + depends_on: + certbot: + condition: service_completed_successfully + deploy: + resources: + reservations: + memory: 4G + limits: + memory: 8G + network_mode: 'host' + + certbot: + image: certbot/certbot + command: certonly --standalone --non-interactive --agree-tos -m menno@vleeuwen.me -d satisfactory.mvl.sh + # Uncomment this when requesting a new certificate, make sure to disable nginx-proxy-manager first since this conflicts with port 80 + # ports: + # - '80:80/tcp' + volumes: + - ./data/certs:/etc/letsencrypt + environment: + - CERTBOT_MAIL=menno@vleeuwen.me + - DOMAIN=satisfactory.mvl.sh diff --git a/stash/docker-compose.yml b/stash/docker-compose.yml new file mode 100644 index 0000000..240996a --- /dev/null +++ b/stash/docker-compose.yml @@ -0,0 +1,38 @@ +services: + stash: + image: stashapp/stash:latest + container_name: stash + restart: unless-stopped + ports: + - "9999:9999" + environment: + - PUID=1000 + - PGID=1000 + - STASH_STASH=/data/ + - STASH_GENERATED=/generated/ + - STASH_METADATA=/metadata/ + - STASH_CACHE=/cache/ + - STASH_PORT=9999 + volumes: + - /etc/localtime:/etc/localtime:ro + + ## Keep configs, scrapers, and plugins here. + - /mnt/services/stash/data/config:/root/.stash + ## Point this at your collection. + - /mnt/stash:/data + ## This is where your stash's metadata lives + - /mnt/services/stash/data/metadata:/metadata + ## Any other cache content. + - /mnt/services/stash/data/cache:/cache + ## Where to store binary blob data (scene covers, images) + - /mnt/services/stash/data/blobs:/blobs + ## Where to store generated content (screenshots,previews,transcodes,sprites) + - /mnt/services/stash/data/generated:/generated + networks: + - shared_network + +networks: + shared_network: + external: true + name: shared_network + \ No newline at end of file diff --git a/static-websites/docker-compose.yml b/static-websites/docker-compose.yml new file mode 100644 index 0000000..1cbefa8 --- /dev/null +++ b/static-websites/docker-compose.yml @@ -0,0 +1,8 @@ +services: + mennovanleeuwen.nl: + restart: unless-stopped + image: nginx + ports: + - 4445:80 + volumes: + - ./mennovanleeuwen.nl/dist:/usr/share/nginx/html \ No newline at end of file diff --git a/static-websites/mennovanleeuwen.nl b/static-websites/mennovanleeuwen.nl new file mode 160000 index 0000000..6ede281 --- /dev/null +++ b/static-websites/mennovanleeuwen.nl @@ -0,0 +1 @@ +Subproject commit 6ede2819a679c2e41120de3848d11c6613ab23bd diff --git a/tool.sh b/tool.sh new file mode 100755 index 0000000..92647d4 --- /dev/null +++ b/tool.sh @@ -0,0 +1,245 @@ +#!/usr/bin/env bash + +# Exit on error. Append "|| true" if you expect an error. +set -o errexit +# Exit on error inside any functions or subshells. +set -o errtrace +# Do not allow use of undefined vars. Use ${VAR:-} to use an undefined VAR +set -o nounset +# Catch error in pipe chains +set -o pipefail + +# Script constants +readonly SCRIPT_NAME=$(basename "${0}") +readonly SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +readonly COMPOSE_FILE="docker-compose.yml" + +# Color constants - using tput for better terminal compatibility +if [[ -t 1 ]]; then + readonly COLOR_RESET="$(tput sgr0)" + readonly COLOR_INFO="$(tput setaf 6)" # Cyan + readonly COLOR_SUCCESS="$(tput setaf 2)" # Green + readonly COLOR_WARNING="$(tput setaf 3)" # Yellow + readonly COLOR_ERROR="$(tput setaf 1)" # Red + readonly COLOR_DEBUG="$(tput setaf 5)" # Magenta +else + readonly COLOR_RESET="" + readonly COLOR_INFO="" + readonly COLOR_SUCCESS="" + readonly COLOR_WARNING="" + readonly COLOR_ERROR="" + readonly COLOR_DEBUG="" +fi + +show_spinner() { + local -r pid="$1" + local -r delay=0.1 + local spinstr='/-\|' + printf " " + tput sc + + while kill -0 "${pid}" 2>/dev/null; do + local temp=${spinstr#?} + tput rc + printf "%s[%c]%s" "${COLOR_WARNING}" "${spinstr}" "${COLOR_RESET}" + local spinstr=${temp}${spinstr%"${temp}"} + sleep "${delay}" + done + tput rc + printf " \r" +} + +log() { + local -r level="$1" + local -r message="$2" + local -r timestamp=$(date +"%Y-%m-%d %H:%M:%S") + local -r use_printf="${3:-false}" + local color + + case "${level}" in + INFO) color="${COLOR_INFO}" ;; + SUCCESS) color="${COLOR_SUCCESS}" ;; + WARNING) color="${COLOR_WARNING}" ;; + ERROR) color="${COLOR_ERROR}" ;; + DEBUG) color="${COLOR_DEBUG}" ;; + *) color="${COLOR_RESET}" ;; + esac + + if [[ "${use_printf}" == true ]]; then + printf "%s[%s] [%s]:%s %s" "${color}" "${timestamp}" "${level}" "${COLOR_RESET}" "${message}" + else + printf "%s[%s] [%s]:%s %s\n" "${color}" "${timestamp}" "${level}" "${COLOR_RESET}" "${message}" + fi +} + +log_info() { log "INFO" "$1" "${2:-false}"; } +log_success() { log "SUCCESS" "$1" "${2:-false}"; } +log_warning() { log "WARNING" "$1" "${2:-false}"; } +log_error() { log "ERROR" "$1" "${2:-false}"; } +log_debug() { log "DEBUG" "$1" "${2:-false}"; } + +# Error handler +trap 'error_handler $? $LINENO $BASH_LINENO "$BASH_COMMAND" $(printf "::%s" ${FUNCNAME[@]:-})' ERR + +error_handler() { + local -r exit_code="$1" + local -r line_number="$2" + local -r bash_lineno="$3" + local -r command="$4" + local -r function_trace="$5" + local -r error_message="Error in ${SCRIPT_NAME}: line ${line_number}, command '${command}' exited with status ${exit_code}" + + log_error "${error_message}" + exit "${exit_code}" +} + +# Docker compose wrapper +docker_compose() { + local -r compose_file="$1" + local -r command="$2" + + if ! docker compose -f "${compose_file}" "${command}" &>/dev/null; then + log_error "Failed to execute: docker compose -f ${compose_file} ${command}" + return 1 + fi +} + +get_container_stats() { + local running_count=0 + local not_running_count=0 + local partially_running_count=0 + + while IFS= read -r -d '' dir; do + local compose_path="${dir}/${COMPOSE_FILE}" + if [[ -f "${compose_path}" ]]; then + local dir_name=$(basename "${dir}") + + # Get expected container count from compose file + local expected_count + expected_count=$(grep -c "image:" "${compose_path}" 2>/dev/null || echo "0") + + # Get actual running container count + local running_containers + running_containers=$(docker compose -f "${compose_path}" ps | grep -c "Up" 2>/dev/null || echo "0") + + # Ensure counts are integers + expected_count=$(echo "$expected_count" | tr -cd '0-9') + running_containers=$(echo "$running_containers" | tr -cd '0-9') + + # Default to 0 if empty + expected_count=${expected_count:-0} + running_containers=${running_containers:-0} + + if [ "$expected_count" -eq "$running_containers" ]; then + log_success "${dir_name}: ${running_containers}/${expected_count}" + running_count=$((running_count + 1)) + elif [ "$running_containers" -eq 0 ]; then + log_error "${dir_name}: ${running_containers}/${expected_count}" + not_running_count=$((not_running_count + 1)) + else + log_warning "${dir_name}: ${running_containers}/${expected_count}" + partially_running_count=$((partially_running_count + 1)) + fi + fi + done < <(find . -maxdepth 1 -type d -print0) + + log_info "Summary:" + log_info " Fully running: ${running_count}" + log_info " Not running: ${not_running_count}" + log_info " Partially running: ${partially_running_count}" +} + +list_containers() { + local -r show_status="${1:-false}" + log_info "Running containers: $(docker ps -q | wc -l)" + + if [[ "${show_status}" == true ]]; then + get_container_stats + fi +} + +stop_containers() { + log_warning "Stopping all containers" + + while IFS= read -r -d '' dir; do + local compose_path="${dir}/${COMPOSE_FILE}" + if [[ -f "${compose_path}" ]]; then + local dir_name=$(basename "${dir}") + log_info "Stopping ${dir_name}" true + docker_compose "${compose_path}" down --remove-orphans & show_spinner $! + echo + fi + done < <(find . -maxdepth 1 -type d -print0) + + list_containers +} + +pull_containers() { + log_warning "Pulling images for all containers" + + while IFS= read -r -d '' dir; do + local compose_path="${dir}/${COMPOSE_FILE}" + if [[ -f "${compose_path}" ]]; then + local dir_name=$(basename "${dir}") + log_info "Pulling ${dir_name}" true + docker_compose "${compose_path}" pull & show_spinner $! + echo + fi + done < <(find . -maxdepth 1 -type d -print0) +} + +start_containers() { + log_warning "Starting up all containers" + + while IFS= read -r -d '' dir; do + local compose_path="${dir}/${COMPOSE_FILE}" + if [[ -f "${compose_path}" ]]; then + local dir_name=$(basename "${dir}") + log_info "Starting ${dir_name}" + docker compose -f "${compose_path}" up -d + fi + done < <(find . -maxdepth 1 -type d -print0) + + list_containers +} + +show_usage() { + cat << EOF +Usage: ${SCRIPT_NAME} [options] + +Docker container management script + +Options: + -h, --help Show this help message + -p, --pull Pull the images for all containers + -s, --start Start all containers + -r, --restart Restart all containers + -u, --update Update all containers (stop, pull, start) + -d, --down Stop all containers + -l, --list List containers and their status + +Examples: + ${SCRIPT_NAME} --start # Start all containers + ${SCRIPT_NAME} --update # Update all containers + ${SCRIPT_NAME} --list # Show container status +EOF +} + +main() { + local args=() + while [[ $# -gt 0 ]]; do + case "$1" in + -h|--help) show_usage; exit 0 ;; + -p|--pull) pull_containers; exit 0 ;; + -s|--start) start_containers; exit 0 ;; + -r|--restart) stop_containers; start_containers; exit 0 ;; + -u|--update) stop_containers; pull_containers; start_containers; exit 0 ;; + -d|--down) stop_containers; exit 0 ;; + -l|--list) list_containers true; exit 0 ;; + *) log_error "Invalid option: $1"; show_usage; exit 1 ;; + esac + done +} + +# Execute main function +main "$@" diff --git a/torrent/docker-compose.yml b/torrent/docker-compose.yml new file mode 100644 index 0000000..010c599 --- /dev/null +++ b/torrent/docker-compose.yml @@ -0,0 +1,43 @@ +services: + gluetun: + image: qmcgaw/gluetun:latest + container_name: gluetun + cap_add: + - NET_ADMIN + networks: + - shared_network + ports: + - 6881:6881 + - 6881:6881/udp + - 8085:8085 + volumes: + - /mnt/services/torrent/data/gluetun:/gluetun + environment: + - PUID=1000 + - PGID=1000 + - VPN_SERVICE_PROVIDER=${VPN_SERVICE_PROVIDER} + - OPENVPN_USER=${OPENVPN_USER} + - OPENVPN_PASSWORD=${OPENVPN_PASSWORD} + - SERVER_COUNTRIES=${SERVER_COUNTRIES} + restart: always + + qbittorrent: + image: lscr.io/linuxserver/qbittorrent + container_name: qbittorrent + network_mode: "service:gluetun" + environment: + - PUID=1000 + - PGID=1000 + - WEBUI_PORT=8085 + volumes: + - "/etc/localtime:/etc/localtime:ro" + - /mnt/services/torrent/data/qbit-config:/config + - /mnt:/storage + depends_on: + - gluetun + restart: always + +networks: + shared_network: + external: true + name: shared_network \ No newline at end of file diff --git a/wireguard/docker-compose.yml b/wireguard/docker-compose.yml new file mode 100644 index 0000000..232224a --- /dev/null +++ b/wireguard/docker-compose.yml @@ -0,0 +1,18 @@ +name: wireguard +services: + server: + image: lscr.io/linuxserver/wireguard:latest + container_name: wireguard + cap_add: + - NET_ADMIN + environment: + - PUID=1000 + - PGID=1000 + - PEERS=s24,pc,laptop + volumes: + - /mnt/services/wireguard/data:/config + ports: + - 51820:51820/udp + sysctls: + - net.ipv4.conf.all.src_valid_mark=1 + restart: unless-stopped