From 540017129808a45fdae9095d765e5e949ca545fc Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Thu, 28 Dec 2023 10:07:43 -0700 Subject: [PATCH] Move homelab to runit --- homelab/.gitignore | 3 - homelab/README.md | 20 +- homelab/TODO.md | 9 - homelab/atlas/run | 19 + homelab/builder-betty/app/.ssh/known_hosts | 3 + homelab/builder-betty/app/config.yaml | 86 +++++ homelab/builder-betty/finish | 3 + homelab/builder-betty/run | 9 + homelab/{ => caddy}/Caddyfile | 8 +- homelab/caddy/finish | 3 + homelab/caddy/run | 13 + homelab/{ => coredns}/Corefile | 2 +- homelab/coredns/finish | 3 + homelab/coredns/run | 8 + homelab/dave.yaml | 4 - homelab/ddns/finish | 3 + homelab/ddns/run | 9 + homelab/deploy.sh | 12 - homelab/docker-compose.yaml | 406 -------------------- homelab/filebrowser.json | 8 - homelab/geneweb/finish | 3 + homelab/geneweb/run | 8 + homelab/gitea/finish | 3 + homelab/{ => gitea}/gitea-robots.txt | 0 homelab/gitea/run | 12 + homelab/{ => gitea}/timezone | 0 homelab/lidarr/finish | 3 + homelab/lidarr/run | 10 + homelab/localtime | Bin 2460 -> 0 bytes homelab/netdata.conf | 5 - homelab/nzbget/finish | 3 + homelab/nzbget/run | 9 + homelab/oscar/finish | 3 + homelab/oscar/run | 20 + homelab/picoshare/finish | 3 + homelab/picoshare/run | 10 + homelab/{www => pigallery2}/deergrove.png | Bin homelab/pigallery2/finish | 3 + homelab/{ => pigallery2}/portal.json | 0 homelab/pigallery2/run | 12 + homelab/plex/finish | 3 + homelab/plex/run | 11 + homelab/portal/deergrove.png | Bin 0 -> 30184 bytes homelab/portal/finish | 3 + homelab/portal/portal.json | 76 ++++ homelab/portal/run | 9 + homelab/prowlarr/finish | 3 + homelab/prowlarr/run | 8 + homelab/radarr/finish | 3 + homelab/radarr/run | 10 + homelab/readarr/finish | 3 + homelab/readarr/run | 11 + homelab/samba/finish | 3 + homelab/samba/run | 17 + homelab/simpleauth/finish | 3 + homelab/simpleauth/run | 9 + homelab/sonarr/finish | 3 + homelab/sonarr/run | 10 + homelab/sucker/finish | 3 + homelab/sucker/run | 15 + homelab/sync.sh | 11 + homelab/sys-backup/run | 14 + homelab/transmission/finish | 3 + homelab/transmission/run | 12 + homelab/unused/docker-compose.rejected.yaml | 58 --- homelab/unused/grafana.ini.tmpl | 10 - homelab/unused/jellyfin.yaml | 363 ----------------- homelab/unused/ocis.yaml | 252 ------------ homelab/unused/periodic/backup-systemd | 3 - homelab/unused/periodic/btrfs-scrub | 9 - homelab/unused/periodic/ddns-update | 38 -- homelab/unused/periodic/gdrive-backup | 11 - homelab/unused/periodic/last-run | 3 - homelab/unused/periodic/nextcloud-cron | 4 - homelab/unused/prometheus.yaml | 7 - homelab/webfs/finish | 3 + homelab/webfs/run | 11 + homelab/www/index.css | 78 ---- homelab/www/index.html | 18 - homelab/www/index.mjs | 109 ------ 80 files changed, 523 insertions(+), 1435 deletions(-) delete mode 100644 homelab/.gitignore delete mode 100644 homelab/TODO.md create mode 100755 homelab/atlas/run create mode 100644 homelab/builder-betty/app/.ssh/known_hosts create mode 100644 homelab/builder-betty/app/config.yaml create mode 100755 homelab/builder-betty/finish create mode 100755 homelab/builder-betty/run rename homelab/{ => caddy}/Caddyfile (93%) create mode 100755 homelab/caddy/finish create mode 100755 homelab/caddy/run rename homelab/{ => coredns}/Corefile (86%) create mode 100755 homelab/coredns/finish create mode 100755 homelab/coredns/run delete mode 100644 homelab/dave.yaml create mode 100755 homelab/ddns/finish create mode 100755 homelab/ddns/run delete mode 100755 homelab/deploy.sh delete mode 100644 homelab/docker-compose.yaml delete mode 100644 homelab/filebrowser.json create mode 100755 homelab/geneweb/finish create mode 100755 homelab/geneweb/run create mode 100755 homelab/gitea/finish rename homelab/{ => gitea}/gitea-robots.txt (100%) create mode 100755 homelab/gitea/run rename homelab/{ => gitea}/timezone (100%) create mode 100755 homelab/lidarr/finish create mode 100755 homelab/lidarr/run delete mode 100644 homelab/localtime delete mode 100644 homelab/netdata.conf create mode 100755 homelab/nzbget/finish create mode 100755 homelab/nzbget/run create mode 100755 homelab/oscar/finish create mode 100755 homelab/oscar/run create mode 100755 homelab/picoshare/finish create mode 100755 homelab/picoshare/run rename homelab/{www => pigallery2}/deergrove.png (100%) create mode 100755 homelab/pigallery2/finish rename homelab/{ => pigallery2}/portal.json (100%) create mode 100755 homelab/pigallery2/run create mode 100755 homelab/plex/finish create mode 100755 homelab/plex/run create mode 100644 homelab/portal/deergrove.png create mode 100755 homelab/portal/finish create mode 100644 homelab/portal/portal.json create mode 100755 homelab/portal/run create mode 100755 homelab/prowlarr/finish create mode 100755 homelab/prowlarr/run create mode 100755 homelab/radarr/finish create mode 100755 homelab/radarr/run create mode 100755 homelab/readarr/finish create mode 100755 homelab/readarr/run create mode 100755 homelab/samba/finish create mode 100755 homelab/samba/run create mode 100755 homelab/simpleauth/finish create mode 100755 homelab/simpleauth/run create mode 100755 homelab/sonarr/finish create mode 100755 homelab/sonarr/run create mode 100755 homelab/sucker/finish create mode 100755 homelab/sucker/run create mode 100755 homelab/sync.sh create mode 100755 homelab/sys-backup/run create mode 100755 homelab/transmission/finish create mode 100755 homelab/transmission/run delete mode 100644 homelab/unused/docker-compose.rejected.yaml delete mode 100644 homelab/unused/grafana.ini.tmpl delete mode 100644 homelab/unused/jellyfin.yaml delete mode 100644 homelab/unused/ocis.yaml delete mode 100755 homelab/unused/periodic/backup-systemd delete mode 100755 homelab/unused/periodic/btrfs-scrub delete mode 100755 homelab/unused/periodic/ddns-update delete mode 100755 homelab/unused/periodic/gdrive-backup delete mode 100755 homelab/unused/periodic/last-run delete mode 100755 homelab/unused/periodic/nextcloud-cron delete mode 100644 homelab/unused/prometheus.yaml create mode 100755 homelab/webfs/finish create mode 100755 homelab/webfs/run delete mode 100644 homelab/www/index.css delete mode 100644 homelab/www/index.html delete mode 100644 homelab/www/index.mjs diff --git a/homelab/.gitignore b/homelab/.gitignore deleted file mode 100644 index b3843ab..0000000 --- a/homelab/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -password -samba-users.env -secrets diff --git a/homelab/README.md b/homelab/README.md index 8eeaf1d..a443ab2 100644 --- a/homelab/README.md +++ b/homelab/README.md @@ -1,19 +1,3 @@ -# Neale's Homelab +My homelab now uses runit-managed podman containers. -This is the stuff I run on my little Raspberry Pi. - -I guess I fiddle around with it pretty frequently. - -## Portal - -In the [www](www) directory is a static HTML/JavaScript portal thing I wrote. -It doesn't need any server configuration, -you just edit the HTML to manage what apps it serves. - -Other things like this exist, -but they all require ridiculous things like relational databases or weird config files. - -I should probably package this up or something, -but then I'd have to put effort into publicizing it, -and run a ticketing system or something, -so meh. \ No newline at end of file +runit essentially runs `*/run` in an endless loop. diff --git a/homelab/TODO.md b/homelab/TODO.md deleted file mode 100644 index 41ce968..0000000 --- a/homelab/TODO.md +++ /dev/null @@ -1,9 +0,0 @@ -* Single Sign-On - * [x] Replace simpleauth with somebody else's project - * [x] Set up Forgejo OIDC to Authelia (there's a guide on Authelia's site) - * [x] Persist "remember me" across reboots -* LDAP restrictions - * [x] People can only r/w their own storage - * [x] Public storage - * [x] Per-Group storage -* [x] Media-Sucker secure setup (bind to 0.0.0.0 opens to internet) diff --git a/homelab/atlas/run b/homelab/atlas/run new file mode 100755 index 0000000..3889f78 --- /dev/null +++ b/homelab/atlas/run @@ -0,0 +1,19 @@ +#! /bin/sh + +me=$(basename $(pwd)) +image=jamesits/ripe-atlas:latest + +podman pull $image +podman rm $me +podman run \ + --name $me \ + --cpu-shares 128 \ + --cap-drop ALL \ + --cap-add CHOWN \ + --cap-add SETUID \ + --cap-add SETGID \ + --cap-add DAC_OVERRIDE \ + --cap-add NET_RAW \ + --volume /srv/sys/atlas/etc:/var/atlas-probe/etc \ + --volume /srv/sys/atlas/status:/var/atlas-probe/status \ + $image diff --git a/homelab/builder-betty/app/.ssh/known_hosts b/homelab/builder-betty/app/.ssh/known_hosts new file mode 100644 index 0000000..94efe99 --- /dev/null +++ b/homelab/builder-betty/app/.ssh/known_hosts @@ -0,0 +1,3 @@ +melville.woozle.org ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC6fMdw0m8wvh5+9IUcNgjxk0TgjoTT1anESnsYWIcnmS8l7PzkB/WfCEZEU0QzKvKXSp37jd30iR5U9jM7zTjYrjCJZvK0dxShC9iIgR5akAThXvlH0KkHVAvhmQda6nvMWQugp359Usp4zH90/J7G//+3HEQ9zfXW+p29bwBOdyDHfjDSIz95ysy8ivwMFKuPgAsNK4FDfBsGVHCM5xu5bn0dSaHeqGn7bneY00zwQqQot6rOw1Pao2tEY04Vu4KC1VKVWKU38dNBEFTOQBxYhiVMsxY3CIwDbEQLA5gjRnYog2KvsDP9XK4W2k1Yc9PvwoinqzcgmDS7isQ8HAoZiY06CChg3hHYXRre+TcO/UrjhzrWbxdCo7XFKBiC74ZU/+t2IkBmmHEnaTpmaLazxZD75wUH9rrWwgPVFEWNp41nj0VfQfR032MwJ2iNbvkCW/2kUWe++r56TlYQjxL8FVICVBbt6pZprMbEkQm3/iPR6ibfNNa620Kz3QRUsxM= +melville.woozle.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBE1D4QQxjnNgmI7wteSAnAqArKQ6UTnTKmTitnU40ISizAK1j8OqXxEv0hbssNrTVyqlmLUoIeRuHd5bHGC8dEE= +melville.woozle.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEQKIumG2Wl3papG4lcIB9+ZEe76uMbfpP+XSlUBjR0E diff --git a/homelab/builder-betty/app/config.yaml b/homelab/builder-betty/app/config.yaml new file mode 100644 index 0000000..4794348 --- /dev/null +++ b/homelab/builder-betty/app/config.yaml @@ -0,0 +1,86 @@ +# 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: 30m + # 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: 28s + # The labels of a runner are used to determine which jobs the runner can run, and how to run them. + labels: ["aarch64", "big-builder", "hugo", "python3", "go"] + +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. + # 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: 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/homelab/builder-betty/finish b/homelab/builder-betty/finish new file mode 100755 index 0000000..0428209 --- /dev/null +++ b/homelab/builder-betty/finish @@ -0,0 +1,3 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman stop $me diff --git a/homelab/builder-betty/run b/homelab/builder-betty/run new file mode 100755 index 0000000..08c6095 --- /dev/null +++ b/homelab/builder-betty/run @@ -0,0 +1,9 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman rm $me +podman run \ + --name $me \ + --volume ./app/config.yaml:/app/config.yaml:ro \ + --volume ./app/.ssh:/app/.ssh:ro \ + --volume /srv/secrets/builder-betty/.runner:/app/.runner:ro \ + git.woozle.org/neale/big-builder:1.0 -c config.yaml daemon diff --git a/homelab/Caddyfile b/homelab/caddy/Caddyfile similarity index 93% rename from homelab/Caddyfile rename to homelab/caddy/Caddyfile index 2d4d300..e1d5d86 100644 --- a/homelab/Caddyfile +++ b/homelab/caddy/Caddyfile @@ -1,5 +1,5 @@ { - email neale@woozle.org + email neale@woozle.org #debug } @@ -21,10 +21,6 @@ drive.woozle.org { #reverse_proxy filebrowser:80 } -media.woozle.org { - reverse_proxy jellyfin:8096 -} - # XXX: have this use caddy auth ancestry.woozle.org { reverse_proxy geneweb:2317 @@ -77,7 +73,7 @@ deergrove.woozle.org { } handle_path /sucker/* { - reverse_proxy host.lan:5801 + reverse_proxy sucker:8080 } handle_path /netdata/* { diff --git a/homelab/caddy/finish b/homelab/caddy/finish new file mode 100755 index 0000000..0428209 --- /dev/null +++ b/homelab/caddy/finish @@ -0,0 +1,3 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman stop $me diff --git a/homelab/caddy/run b/homelab/caddy/run new file mode 100755 index 0000000..61c9d75 --- /dev/null +++ b/homelab/caddy/run @@ -0,0 +1,13 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman rm $me +podman run \ + --name $me \ + --network homelab \ + --publish 80:80 \ + --publish 443:443 \ + --volume /srv:/srv:ro \ + --volume /srv/sys/caddy:/data/caddy \ + --volume ./Caddyfile:/etc/caddy/Caddyfile:ro \ + --add-host host.lan:192.168.86.2 \ + caddy:2-alpine diff --git a/homelab/Corefile b/homelab/coredns/Corefile similarity index 86% rename from homelab/Corefile rename to homelab/coredns/Corefile index 88f5648..3f5254a 100644 --- a/homelab/Corefile +++ b/homelab/coredns/Corefile @@ -4,5 +4,5 @@ 192.168.86.2 sweetums.woozle.org deergrove.woozle.org drive.woozle.org git.woozle.org ancestry.woozle.org media.woozle.org photos.woozle.org auth.woozle.org xfer.woozle.org fallthrough } - forward . 8.8.8.8 + forward . 1.1.1.1 1.0.0.1 8.8.8.8 } diff --git a/homelab/coredns/finish b/homelab/coredns/finish new file mode 100755 index 0000000..0428209 --- /dev/null +++ b/homelab/coredns/finish @@ -0,0 +1,3 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman stop $me diff --git a/homelab/coredns/run b/homelab/coredns/run new file mode 100755 index 0000000..242fcd9 --- /dev/null +++ b/homelab/coredns/run @@ -0,0 +1,8 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman rm $me +podman run \ + --name $me \ + --network host \ + --mount type=bind,src=$(pwd)/Corefile,dst=/home/nonroot/Corefile,readonly=true \ + coredns/coredns diff --git a/homelab/dave.yaml b/homelab/dave.yaml deleted file mode 100644 index b5ae6cf..0000000 --- a/homelab/dave.yaml +++ /dev/null @@ -1,4 +0,0 @@ -address: "0.0.0.0" -port: "8000" -dir: "/data" -prefix: "/" diff --git a/homelab/ddns/finish b/homelab/ddns/finish new file mode 100755 index 0000000..0428209 --- /dev/null +++ b/homelab/ddns/finish @@ -0,0 +1,3 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman stop $me diff --git a/homelab/ddns/run b/homelab/ddns/run new file mode 100755 index 0000000..5f12b3b --- /dev/null +++ b/homelab/ddns/run @@ -0,0 +1,9 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman rm $me +podman run \ + --name $me \ + --network homelab \ + --dns 1.1.1.1 \ + --volume /srv/sys/ddns-updater:/updater/data \ + qmcgaw/ddns-updater diff --git a/homelab/deploy.sh b/homelab/deploy.sh deleted file mode 100755 index 60239bc..0000000 --- a/homelab/deploy.sh +++ /dev/null @@ -1,12 +0,0 @@ -#! /bin/sh - -stack=$(basename $(pwd)) - -extra="--resolve-image changed" -if [ "$1" = "--slow" ]; then - extra= - shift -fi - -docker --context deergrove stack deploy -c docker-compose.yaml --prune $extra "$@" $stack -#docker --context deergrove compose up --detach diff --git a/homelab/docker-compose.yaml b/homelab/docker-compose.yaml deleted file mode 100644 index f84ea80..0000000 --- a/homelab/docker-compose.yaml +++ /dev/null @@ -1,406 +0,0 @@ -version: "3.8" -services: - coredns: - image: coredns/coredns - networks: - - hostnet - command: - - -conf - - /Corefile - configs: - - source: Corefile - target: /Corefile - - caddy: - image: caddy:2-alpine - ports: - - target: 443 - published: 443 - mode: host - - target: 80 - published: 80 - mode: host - volumes: - - type: bind - source: /srv - target: /srv - read_only: true - - type: bind - source: /srv/sys/caddy - target: /data/caddy - configs: - - source: Caddyfile - target: /etc/caddy/Caddyfile - extra_hosts: - - host.docker.internal:host-gateway - - host.lan:192.168.86.2 - - simpleauth: - image: git.woozle.org/neale/simpleauth - secrets: - - passwd - - simpleauth.key - - portal: - image: git.woozle.org/neale/portal - configs: - - source: portal.json - target: /web/portal.json - - source: deergrove.png - target: /web/portal.png - - jellyfin: - image: jellyfin/jellyfin - deploy: - replicas: 0 - environment: - TZ: US/Mountain - volumes: - - type: bind - source: /srv/sys/jellyfin/config - target: /config - - type: bind - source: /srv/sys/jellyfin/cache - target: /cache - - type: bind - source: /srv/media/ - target: /srv/media/ - read_only: true - - plex: - image: lscr.io/linuxserver/plex:latest - networks: - - hostnet - environment: - TZ: US/Mountain - VERSION: public - volumes: - - type: bind - source: /srv/sys/plex - target: /config - - type: bind - source: /srv/media/ - target: /srv/media/ - read_only: true - - pigallery2: - image: bpatrik/pigallery2:latest - volumes: - - type: bind - source: /srv/sys/pigallery2/config - target: /app/data/config - - type: bind - source: /srv/sys/pigallery2/db - target: /app/data/db - - type: bind - source: /srv/sys/pigallery2/cache - target: /app/data/cache - - type: bind - source: /srv/storage/fam/Photos - target: /photos/fam - read_only: true - - type: bind - source: /srv/storage/ginnie/Photos - target: /photos/ginnie - read_only: true - - transmission: - image: lscr.io/linuxserver/transmission:latest - volumes: - - type: bind - source: /srv/sys/transmission - target: /config - - type: bind - source: /srv/incoming - target: /srv/incoming - environment: - PEERPORT: "51413" - ports: - - 51413:51413 - - 51413:51413/udp - - sonarr: - image: lscr.io/linuxserver/sonarr - extra_hosts: - - host.docker.internal:host-gateway - volumes: - - type: bind - source: /srv/sys/sonarr - target: /config - - type: bind - source: /srv/media/tv - target: /srv/media/tv - - type: bind - source: /srv/incoming - target: /srv/incoming - radarr: - image: lscr.io/linuxserver/radarr - extra_hosts: - - host.docker.internal:host-gateway - volumes: - - type: bind - source: /srv/sys/radarr - target: /config - - type: bind - source: /srv/media/movies - target: /srv/media/movies - - type: bind - source: /srv/incoming - target: /srv/incoming - lidarr: - image: lscr.io/linuxserver/lidarr - extra_hosts: - - host.docker.internal:host-gateway - volumes: - - type: bind - source: /srv/sys/lidarr - target: /config - - type: bind - source: /srv/media/music - target: /srv/media/music - - type: bind - source: /srv/incoming - target: /srv/incoming - readarr: - image: lscr.io/linuxserver/readarr:develop - extra_hosts: - - host.docker.internal:host-gateway - volumes: - - type: bind - source: /srv/sys/readarr - target: /config - - type: bind - source: /srv/media/books - target: /srv/media/books - - type: bind - source: /srv/media/audiobooks - target: /srv/media/audiobooks - - type: bind - source: /srv/incoming - target: /srv/incoming - prowlarr: - image: lscr.io/linuxserver/prowlarr:latest - extra_hosts: - - host.docker.internal:host-gateway - volumes: - - type: bind - source: /srv/sys/prowlarr - target: /config - - nzbget: - image: lscr.io/linuxserver/nzbget - volumes: - - type: bind - source: /srv/sys/nzbget - target: /config - - type: bind - source: /srv/incoming - target: /srv/incoming - - gitea: - image: codeberg.org/forgejo/forgejo:1.20.5-0-rootless - configs: - - source: gitea-robots.txt - target: /var/lib/gitea/custom/robots.txt - - source: timezone - target: /etc/timezone - - source: localtime - target: /etc/localtime - volumes: - - type: bind - source: /srv/sys/gitea/app.ini - target: /etc/gitea/app.ini - - type: bind - source: /srv/sys/gitea - target: /data - - atlas: - image: ctassisf/ripe-atlas-alpine:arm64v8 - volumes: - - type: bind - source: /srv/sys/atlas/etc - target: /var/atlas-probe/etc - - type: bind - source: /srv/sys/atlas/status - target: /var/atlas-probe/status - - netdata: - image: netdata/netdata - hostname: "{{.Node.Hostname}}" - deploy: - replicas: 0 - environment: - NETDATA_DISABLE_CLOUD: "1" - cap_add: - - SYS_PTRACE - volumes: - - type: bind - source: / - target: /host - read_only: true - - type: bind - source: /srv/sys/netdata/lib - target: /var/lib/netdata - - type: bind - source: /srv/sys/netdata/cache - target: /var/cache/netdata - configs: - - source: netdata.conf - target: /etc/netdata/netdata.conf - - - geneweb: - image: ravermeister/geneweb - volumes: - - type: bind - source: /srv/sys/geneweb/ - target: /usr/local/share/geneweb/share/data - - samba: - image: dperson/samba - volumes: - - type: bind - source: /srv - target: /srv - environment: - NMBD: enable - RECYCLE: disable - USERID: 911 - GROUPID: 911 - # name;path;browse;readonly;guest - SHARE1: drive;/srv;yes;no;no - SHARE2: retropie;/srv/media/games/retropie;yes;yes;yes - env_file: - - secrets/samba-users.env - ports: - - published: 139 - target: 139 - - published: 445 - target: 445 - - webfs: - image: sigoden/dufs - volumes: - - type: bind - source: /srv/storage - target: /srv/storage - - type: bind - source: /srv/incoming - target: /srv/incoming - - type: bind - source: /srv/media - target: /srv/media - command: - - -A - - /srv - user: "911:911" - - picoshare: - image: git.woozle.org/neale/picoshare - volumes: - - type: bind - source: /srv/sys/picoshare - target: /data - environment: - PS_SHARED_SECRET_FILE: /run/secrets/picoshare - secrets: - - picoshare - - ddns: - image: qmcgaw/ddns-updater - dns: - - 1.1.1.1 - volumes: - - type: bind - source: /srv/sys/ddns-updater - target: /updater/data - - filebrowser: - image: filebrowser/filebrowser - volumes: - - type: bind - source: /srv/sys/filebrowser/database - target: /database - - type: bind - source: /srv/storage - target: /srv/storage - - type: bind - source: /srv/media - target: /srv/media - - type: bind - source: /srv/incoming - target: /srv/incoming - user: "911:911" - configs: - - source: filebrowser.json - target: /.filebrowser.json - - -configs: - dave.yaml: - file: dave.yaml - name: dave.yaml-v3 - Corefile: - file: Corefile - name: Corefile-v11 - Caddyfile: - file: Caddyfile - name: Caddyfile-v153 - portal.json: - file: portal.json - name: portal.json-v7 - deergrove.png: - file: www/deergrove.png - name: deergrove.png-v1 - netdata.conf: - file: netdata.conf - name: netdata.conf-v1 - gitea-robots.txt: - file: gitea-robots.txt - name: gitea-robots.txt-v1 - filebrowser.json: - file: filebrowser.json - name: filebrowser.json-v2 - localtime: - file: localtime - name: localtime-v1 - timezone: - file: timezone - name: timezone-v1 - -secrets: - passwd: - file: secrets/passwd - name: passwd-v2 - simpleauth.key: - file: secrets/simpleauth.key - name: simpleauth.key-v1 - tunnel: - file: secrets/tunnel - name: tunnel-v1 - known_hosts: - file: secrets/known_hosts - name: known_hosts-v1 - jwt.secret: - file: secrets/jwt.secret - name: jwt.secret-v1 - storage.secret: - file: secrets/storage.secret - name: storage.secret-v1 - session.secret: - file: secrets/session.secret - name: session.secret-v1 - users.yaml: - file: secrets/users.yaml - name: users.yaml-v9 - authelia.oidc.yaml: - file: secrets/authelia.oidc.yaml - name: authelia.oidc.yaml-v2 - picoshare: - file: secrets/picoshare - name: picoshare-v1 - -networks: - hostnet: - external: true - name: host diff --git a/homelab/filebrowser.json b/homelab/filebrowser.json deleted file mode 100644 index 5ae1ec9..0000000 --- a/homelab/filebrowser.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "port": 80, - "baseURL": "/", - "address": "", - "log": "stdout", - "database": "/database/filebrowser.db", - "root": "/srv" -} diff --git a/homelab/geneweb/finish b/homelab/geneweb/finish new file mode 100755 index 0000000..0428209 --- /dev/null +++ b/homelab/geneweb/finish @@ -0,0 +1,3 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman stop $me diff --git a/homelab/geneweb/run b/homelab/geneweb/run new file mode 100755 index 0000000..5a55dc3 --- /dev/null +++ b/homelab/geneweb/run @@ -0,0 +1,8 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman rm $me +podman run \ + --name $me \ + --network homelab \ + --volume /srv/sys/geneweb:/usr/local/share/geneweb/share/data \ + ravermeister/geneweb diff --git a/homelab/gitea/finish b/homelab/gitea/finish new file mode 100755 index 0000000..0428209 --- /dev/null +++ b/homelab/gitea/finish @@ -0,0 +1,3 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman stop $me diff --git a/homelab/gitea-robots.txt b/homelab/gitea/gitea-robots.txt similarity index 100% rename from homelab/gitea-robots.txt rename to homelab/gitea/gitea-robots.txt diff --git a/homelab/gitea/run b/homelab/gitea/run new file mode 100755 index 0000000..a544545 --- /dev/null +++ b/homelab/gitea/run @@ -0,0 +1,12 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman rm $me +podman run \ + --name $me \ + --network homelab \ + --volume ./gitea-robots.txt:/var/lib/gitea/custom/robots.txt:ro \ + --volume ./timezone:/etc/timezone:ro \ + --volume /etc/localtime:/etc/localtime:ro \ + --volume /srv/sys/gitea/app.ini:/etc/gitea/app.ini \ + --volume /srv/sys/gitea:/data \ + codeberg.org/forgejo/forgejo:1.20.5-0-rootless diff --git a/homelab/timezone b/homelab/gitea/timezone similarity index 100% rename from homelab/timezone rename to homelab/gitea/timezone diff --git a/homelab/lidarr/finish b/homelab/lidarr/finish new file mode 100755 index 0000000..0428209 --- /dev/null +++ b/homelab/lidarr/finish @@ -0,0 +1,3 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman stop $me diff --git a/homelab/lidarr/run b/homelab/lidarr/run new file mode 100755 index 0000000..7731088 --- /dev/null +++ b/homelab/lidarr/run @@ -0,0 +1,10 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman rm $me +podman run \ + --name $me \ + --network homelab \ + --volume /srv/sys/lidarr:/config \ + --volume /srv/media/music:/srv/media/music \ + --volume /srv/incoming:/srv/incoming \ + lscr.io/linuxserver/lidarr diff --git a/homelab/localtime b/homelab/localtime deleted file mode 100644 index abb2b974a47eb3e5c8b4f5d4370baf4898b239ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2460 zcmd_rdrZ}39LMnoL@p;TPbG$MG}96x?n(lgkwJubg764OBa8ys(F(kD(n5R+lJQ65 zSutjr1WH~QMdSAS4@>il|dYpCceyr}y+_NfosBlYmy z-y4T(;>4A7pB|gvDgKD@=&RvAadqq|IsUyzOq{EflON;>|FK*dc+)Aw&IB3M<`=#&Rw74~Abj*ur*#DPQ7F}g=xcd=JTo~(ju;Je_r0OwNBjVt(DVO6^Yp5`{eZ8Bym&Hd>J>VP|b*N$oSwy760ozo$zIZ zat?>QJ-E0;m-~X%3TLWzul!oMCt`F(_9<2IO^Wo)`bv0)qU9?8kXYR}Djyoz zFREIH<->#RqPq5|T+_W?JmNZ|Yueh>qp64WWA$ED8`Y`nib_=7WuLB3OjY%#J=z-< zqr3<5^tx|P0f#S^|<`Q*V-(NK{f8#{)@hU`hXvEiuL6njB#F6|PV{o~q~ zb6ELCKG$2~I@OlJ<9h3uPd(G!tDimRQBBP)dfTx))m&Ytx9@bSDM7)1{e?{Z`^&W# z{{;hq-JL=N0&n*Og_!SJgkSqKZzAn`x!mOzt^)I{Fi)j<%G_p4BFOyNPxrrAVZdB< zNMt{qHictki0jimVk`tktX*SuV0(WWmUat!Bx{nvq2#t46zQzOZi2 zEF4%l$I_9tBa25?k1QWqztt1~sesj#0I2~|1f&WaWkBk{Q3#|G9Hl^N!BGsP8XV<7 z>cLSEq#{U3keXOcQIM)2WkKqK6b7jbQW~T-NO6$raFhqB4@ZHJ3Rz8wkQ!M{k&r5J zlnJR5QYfTSNU4xoA;m(fg_H}a7g8{!Vo1r5npsWJkg9Q%4XGPP;gHI4ln$vKNAZyA zA>~8rhZGR0pw*NRsiD;r5viiplo6>TMZsV+x(k@_M9MkQ+;Br0!Nzc%<@3>5>(` Zg+=D)A;q;IEh{Y}#g&5 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 R%onGMU3fE=kq#Seo*j@n;$2+m* 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 literal 0 HcmV?d00001 diff --git a/homelab/portal/finish b/homelab/portal/finish new file mode 100755 index 0000000..0428209 --- /dev/null +++ b/homelab/portal/finish @@ -0,0 +1,3 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman stop $me diff --git a/homelab/portal/portal.json b/homelab/portal/portal.json new file mode 100644 index 0000000..d7577db --- /dev/null +++ b/homelab/portal/portal.json @@ -0,0 +1,76 @@ +[ + { + "title": "Storage", + "href": "https://drive.woozle.org/", + "icon": "https://drive.woozle.org/storage/public/icons/cloud-folder.png", + "target": "_blank" + }, + { + "title": "Photos", + "href": "https://photos.woozle.org/", + "icon": "https://photos.woozle.org/icon.png", + "target": "_blank" + }, + { + "title": "Git", + "href": "https://git.woozle.org/", + "icon": "https://git.woozle.org/assets/img/logo.svg", + "target": "_blank" + }, + { + "title": "Genealogy", + "href": "https://ancestry.woozle.org/", + "icon": "https://ancestry.woozle.org/images/arbre_start.png", + "target": "_blank" + }, + { + "title": "Movies", + "href": "https://deergrove.woozle.org/radarr/", + "icon": "/radarr/Content/Images/logo.svg" + }, + { + "title": "Episodes", + "href": "https://deergrove.woozle.org/sonarr/", + "icon": "/sonarr/Content/Images/logo.svg" + }, + { + "title": "Music", + "href": "https://deergrove.woozle.org/lidarr/", + "icon": "/lidarr/Content/Images/logo.svg" + }, + { + "title": "Books", + "href": "https://deergrove.woozle.org/readarr/", + "icon": "/readarr/Content/Images/logo.svg" + }, + { + "title": "Media Sucker", + "href": "https://deergrove.woozle.org/sucker/", + "icon": "/sucker/cd-dvd.svg" + }, + { + "title": "Searcher", + "href": "https://deergrove.woozle.org/prowlarr/", + "icon": "/prowlarr/Content/Images/logo.png" + }, + { + "title": "Usenet", + "href": "https://deergrove.woozle.org/nzbget/", + "icon": "/nzbget/img/favicon-256x256.png" + }, + { + "title": "BitTorrent", + "href": "https://deergrove.woozle.org/transmission/web/", + "icon": "/transmission/web/images/webclip-icon.png" + }, + { + "title": "3D Printer", + "href": "https://deergrove.woozle.org/octoprint/", + "icon": "/octoprint/static/img/logo.png" + }, + { + "title": "Host Stats", + "href": "/stat.html", + "app": "stat" + } +] diff --git a/homelab/portal/run b/homelab/portal/run new file mode 100755 index 0000000..5803787 --- /dev/null +++ b/homelab/portal/run @@ -0,0 +1,9 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman rm $me +podman run \ + --name $me \ + --network homelab \ + --volume ./portal.json:/web/portal.json:ro \ + --volume ./deergrove.png:/web/portal.png:ro \ + git.woozle.org/neale/portal diff --git a/homelab/prowlarr/finish b/homelab/prowlarr/finish new file mode 100755 index 0000000..0428209 --- /dev/null +++ b/homelab/prowlarr/finish @@ -0,0 +1,3 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman stop $me diff --git a/homelab/prowlarr/run b/homelab/prowlarr/run new file mode 100755 index 0000000..f0e567a --- /dev/null +++ b/homelab/prowlarr/run @@ -0,0 +1,8 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman rm $me +podman run \ + --name $me \ + --network homelab \ + --volume /srv/sys/prowlarr:/config \ + lscr.io/linuxserver/prowlarr diff --git a/homelab/radarr/finish b/homelab/radarr/finish new file mode 100755 index 0000000..0428209 --- /dev/null +++ b/homelab/radarr/finish @@ -0,0 +1,3 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman stop $me diff --git a/homelab/radarr/run b/homelab/radarr/run new file mode 100755 index 0000000..bb3cc72 --- /dev/null +++ b/homelab/radarr/run @@ -0,0 +1,10 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman rm $me +podman run \ + --name $me \ + --network homelab \ + --volume /srv/sys/radarr:/config \ + --volume /srv/media/movies:/srv/media/movies \ + --volume /srv/incoming:/srv/incoming \ + lscr.io/linuxserver/radarr diff --git a/homelab/readarr/finish b/homelab/readarr/finish new file mode 100755 index 0000000..0428209 --- /dev/null +++ b/homelab/readarr/finish @@ -0,0 +1,3 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman stop $me diff --git a/homelab/readarr/run b/homelab/readarr/run new file mode 100755 index 0000000..45a6d8d --- /dev/null +++ b/homelab/readarr/run @@ -0,0 +1,11 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman rm $me +podman run \ + --name $me \ + --network homelab \ + --volume /srv/sys/readarr:/config \ + --volume /srv/media/books:/srv/media/books \ + --volume /srv/media/audiobooks:/srv/media/audiobooks \ + --volume /srv/incoming:/srv/incoming \ + lscr.io/linuxserver/readarr:develop diff --git a/homelab/samba/finish b/homelab/samba/finish new file mode 100755 index 0000000..0428209 --- /dev/null +++ b/homelab/samba/finish @@ -0,0 +1,3 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman stop $me diff --git a/homelab/samba/run b/homelab/samba/run new file mode 100755 index 0000000..82fdc32 --- /dev/null +++ b/homelab/samba/run @@ -0,0 +1,17 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman rm $me +podman run \ + --name $me \ + --network homelab \ + --publish 139:139 \ + --publish 445:445 \ + --env NMBD=enable \ + --env RECYCLE=disable \ + --env USERID=911 \ + --env GROUPID=911 \ + --env SHARE1='drive;/srv;yes;no;no' \ + --env SHARE2='media;/srv/media;yes;yes;yes' \ + --env-file /srv/secrets/samba-users.env \ + --volume /srv:/srv \ + dperson/samba diff --git a/homelab/simpleauth/finish b/homelab/simpleauth/finish new file mode 100755 index 0000000..0428209 --- /dev/null +++ b/homelab/simpleauth/finish @@ -0,0 +1,3 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman stop $me diff --git a/homelab/simpleauth/run b/homelab/simpleauth/run new file mode 100755 index 0000000..9b966f5 --- /dev/null +++ b/homelab/simpleauth/run @@ -0,0 +1,9 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman rm $me +podman run \ + --name $me \ + --network homelab \ + --volume /srv/secrets/passwd:/run/secrets/passwd:ro \ + --volume /srv/secrets/simpleauth.key:/run/secrets/simpleauth.key:ro \ + git.woozle.org/neale/simpleauth diff --git a/homelab/sonarr/finish b/homelab/sonarr/finish new file mode 100755 index 0000000..0428209 --- /dev/null +++ b/homelab/sonarr/finish @@ -0,0 +1,3 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman stop $me diff --git a/homelab/sonarr/run b/homelab/sonarr/run new file mode 100755 index 0000000..dd794c6 --- /dev/null +++ b/homelab/sonarr/run @@ -0,0 +1,10 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman rm $me +podman run \ + --name $me \ + --network homelab \ + --volume /srv/sys/sonarr:/config \ + --volume /srv/media/tv:/srv/media/tv \ + --volume /srv/incoming:/srv/incoming \ + lscr.io/linuxserver/sonarr diff --git a/homelab/sucker/finish b/homelab/sucker/finish new file mode 100755 index 0000000..0428209 --- /dev/null +++ b/homelab/sucker/finish @@ -0,0 +1,3 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman stop $me diff --git a/homelab/sucker/run b/homelab/sucker/run new file mode 100755 index 0000000..c19f5cb --- /dev/null +++ b/homelab/sucker/run @@ -0,0 +1,15 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman rm $me +podman run \ + --name=$me \ + --device-cgroup-rule 'b 11:* rmw' \ + --network homelab \ + -v /dev:/hdev \ + -v /srv/ext/incoming/sucker:/incoming/sucker \ + --cpu-shares 256 \ + --user 911:19 \ + git.woozle.org/neale/media-sucker \ + -incoming /incoming/sucker \ + -drive /hdev/sr0 /hdev/sr1 /hdev/sr2 + diff --git a/homelab/sync.sh b/homelab/sync.sh new file mode 100755 index 0000000..5105091 --- /dev/null +++ b/homelab/sync.sh @@ -0,0 +1,11 @@ +#! /bin/sh + +service=/host/etc/service +if ! [ -d $service ]; then + echo "=== $service is not a directory" 1>&2 + exit 1 +fi + +rsync -vaxp --delete \ + --exclude=supervise/ \ + $service/* . diff --git a/homelab/sys-backup/run b/homelab/sys-backup/run new file mode 100755 index 0000000..e6df093 --- /dev/null +++ b/homelab/sys-backup/run @@ -0,0 +1,14 @@ +#! /bin/sh + +set -e + +. /etc/lbu/lbu.conf + +hostname=$(hostname) +mkdir -p /srv/backups/$hostname/ +install -p -m 0600 /media/$LBU_MEDIA/$hostname.*.tar.gz /srv/backups/$hostname/ +for path in /srv/backups/$hostname/$hostname.*.tar.gz; do + filename=$(basename $path) + [ -f /media/$LBU_MEDIA/$filename ] || rm $path +done +sleep 4h diff --git a/homelab/transmission/finish b/homelab/transmission/finish new file mode 100755 index 0000000..0428209 --- /dev/null +++ b/homelab/transmission/finish @@ -0,0 +1,3 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman stop $me diff --git a/homelab/transmission/run b/homelab/transmission/run new file mode 100755 index 0000000..80c5065 --- /dev/null +++ b/homelab/transmission/run @@ -0,0 +1,12 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman rm $me +podman run \ + --name $me \ + --network homelab \ + --publish 51413:51413 \ + --publish 51413:51413/udp \ + --env PEERPORT=51413 \ + --volume /srv/sys/transmission:/config \ + --volume /srv/incoming:/srv/incoming \ + lscr.io/linuxserver/transmission:latest diff --git a/homelab/unused/docker-compose.rejected.yaml b/homelab/unused/docker-compose.rejected.yaml deleted file mode 100644 index fd28265..0000000 --- a/homelab/unused/docker-compose.rejected.yaml +++ /dev/null @@ -1,58 +0,0 @@ -version: "3.8" -services: - syncthing: - image: syncthing/syncthing - environment: - PUID: 911 - CGID: 911 - volumes: - - type: bind - source: /srv/ext/sys/syncthing - target: /var/syncthing - - type: bind - source: /srv/ext - target: /srv/ext - ports: - - published: 22000 - target: 22000 - protocol: tcp - - published: 22000 - target: 22000 - protocol: udp - - published: 21027 - target: 21027 - protocol: udp - deploy: - labels: - traefik.enable: "true" - traefik.http.routers.syncthing.rule: "PathPrefix(`/syncthing`)" - traefik.http.routers.syncthing.middlewares: syncthing-striparoo - traefik.http.middlewares.syncthing-striparoo.stripprefix.prefixes: "/syncthing" - traefik.http.services.syncthing.loadbalancer.server.port: "8384" - -## Drop this in to get a netdata container. -## It uses a lot of RAM and causes my machine to swap. -## Granted, it's a lot more lightweight than nextcloud. -## But I can live without netdata. - netdata: - image: netdata/netdata - hostname: $HOSTNAME - volumes: - - type: bind - source: / - target: /host - read_only: true - configs: - - source: netdata.conf - target: /etc/netdata/netdata.conf - deploy: - labels: - traefik.http.routers.netdata.rule: "PathPrefix(`/netdata`)" - traefik.http.middlewares.netdata-striparoo.stripprefix.prefixes: "/netdata" - traefik.http.routers.netdata.middlewares: netdata-striparoo - traefik.http.services.netdata.loadbalancer.server.port: "19999" - -configs: - netdata.conf: - file: netdata.conf - name: netdata.conf-v4 diff --git a/homelab/unused/grafana.ini.tmpl b/homelab/unused/grafana.ini.tmpl deleted file mode 100644 index e4f559e..0000000 --- a/homelab/unused/grafana.ini.tmpl +++ /dev/null @@ -1,10 +0,0 @@ -[server] -domain = {{.Node.Hostname}} -root_url = %(protocol)s://%(domain)s:%(http_port)s/grafana/ -serve_from_sub_path = true - -[auth.anonymous] -enabled = false -org_name = Main Org. -org_role = Viewer - diff --git a/homelab/unused/jellyfin.yaml b/homelab/unused/jellyfin.yaml deleted file mode 100644 index 70a602d..0000000 --- a/homelab/unused/jellyfin.yaml +++ /dev/null @@ -1,363 +0,0 @@ -version: "3.8" -services: - coredns: - image: coredns/coredns - networks: - - hostnet - configs: - - source: Corefile - target: /Corefile - - caddy: - image: caddy:2-alpine - ports: - - target: 443 - published: 443 - mode: host - - target: 80 - published: 80 - mode: host - volumes: - - type: bind - source: /srv - target: /srv - read_only: true - - type: bind - source: /srv/sys/caddy - target: /data/caddy - configs: - - source: Caddyfile - target: /etc/caddy/Caddyfile - - source: index.html - target: /www/index.html - - source: index.mjs - target: /www/index.mjs - - source: deergrove.png - target: /www/deergrove.png - - source: index.css - target: /www/index.css - - source: browser.html - target: /browser.html - extra_hosts: - - host.docker.internal:host-gateway - - authelia: - image: authelia/authelia - environment: - AUTHELIA_JWT_SECRET_FILE: /run/secrets/jwt.secret - AUTHELIA_SESSION_SECRET_FILE: /run/secrets/session.secret - AUTHELIA_STORAGE_ENCRYPTION_FILE: /run/secrets/storage.secret - secrets: - - jwt.secret - - session.secret - - storage.secret - - users.yaml - configs: - - source: authelia.yaml - target: /config/configuration.yml - volumes: - - type: bind - source: /srv/sys/authelia - target: /srv/sys/authelia - - jellyfin: - image: jellyfin/jellyfin - environment: - TZ: US/Mountain - volumes: - - type: bind - source: /srv/sys/jellyfin/config - target: /config - - type: bind - source: /srv/sys/jellyfin/cache - target: /cache - - type: bind - source: /srv/media - target: /srv/media - read_only: true - - plex: - image: ghcr.io/linuxserver/plex:1.29.2 - networks: - - hostnet - environment: - TZ: US/Mountain - VERSION: public - volumes: - - type: bind - source: /srv/sys/plex - target: /config - - type: bind - source: /srv - target: /srv - read_only: true - - transmission: - image: lscr.io/linuxserver/transmission - volumes: - - type: bind - source: /srv/sys/transmission - target: /config - - type: bind - source: /srv/incoming - target: /srv/incoming - networks: - - hostnet - - sonarr: - image: lscr.io/linuxserver/sonarr - extra_hosts: - - host.docker.internal:host-gateway - volumes: - - type: bind - source: /srv/sys/sonarr - target: /config - - type: bind - source: /srv/media/tv - target: /srv/media/tv - - type: bind - source: /srv/incoming - target: /srv/incoming - radarr: - image: lscr.io/linuxserver/radarr - extra_hosts: - - host.docker.internal:host-gateway - volumes: - - type: bind - source: /srv/sys/radarr - target: /config - - type: bind - source: /srv/media/movies - target: /srv/media/movies - - type: bind - source: /srv/incoming - target: /srv/incoming - lidarr: - image: lscr.io/linuxserver/lidarr - extra_hosts: - - host.docker.internal:host-gateway - volumes: - - type: bind - source: /srv/sys/lidarr - target: /config - - type: bind - source: /srv/media/music - target: /srv/media/music - - type: bind - source: /srv/incoming - target: /srv/incoming - readarr: - image: lscr.io/linuxserver/readarr:develop - extra_hosts: - - host.docker.internal:host-gateway - volumes: - - type: bind - source: /srv/sys/readarr - target: /config - - type: bind - source: /srv/media/books - target: /srv/media/books - - type: bind - source: /srv/media/audiobooks - target: /srv/media/audiobooks - - type: bind - source: /srv/incoming - target: /srv/incoming - prowlarr: - image: lscr.io/linuxserver/prowlarr:latest - extra_hosts: - - host.docker.internal:host-gateway - volumes: - - type: bind - source: /srv/sys/prowlarr - target: /config - - nzbget: - image: lscr.io/linuxserver/nzbget - volumes: - - type: bind - source: /srv/sys/nzbget - target: /config - - type: bind - source: /srv/incoming - target: /srv/incoming - - forgejo: - image: codeberg.org/forgejo/forgejo:1.18-rootless - secrets: - - source: forgejo.ini - target: /etc/gitea/app.ini - uid: "1000" - gid: "1000" - mode: 0400 - volumes: - - type: bind - source: /srv/sys/forgejo - target: /data - - type: bind - source: /etc/timezone - target: /etc/timezone - read_only: true - - type: bind - source: /etc/localtime - target: /etc/localtime - read_only: true - - atlas: - image: ctassisf/ripe-atlas-alpine:arm64v8 - volumes: - - type: bind - source: /srv/sys/atlas/etc - target: /var/atlas-probe/etc - - type: bind - source: /srv/sys/atlas/status - target: /var/atlas-probe/status - - geneweb: - image: ravermeister/geneweb - volumes: - - type: bind - source: /srv/sys/geneweb/etc - target: /usr/local/share/geneweb/etc - - type: bind - source: /srv/sys/geneweb/share/data - target: /usr/local/share/geneweb/share/data - - type: bind - source: /srv/sys/geneweb/log - target: /usr/local/share/geneweb/log - - samba: - image: dperson/samba - volumes: - - type: bind - source: /srv - target: /srv - bind: - propagation: rslave - environment: - NMBD: enable - RECYCLE: disable - USERID: 911 - GROUPID: 911 - # name;path;browse;readonly;guest - SHARE1: drive;/srv;yes;no;no - SHARE2: retropie;/srv/media/games/retropie;yes;yes;yes - env_file: - - secrets/samba-users.env - ports: - - published: 139 - target: 139 - - published: 445 - target: 445 - - webdav: - image: micromata/dave - volumes: - - type: bind - source: /srv - target: /data - configs: - - source: dave.yaml - target: /config/config.yaml - user: "911:911" - - ddns: - image: qmcgaw/ddns-updater - dns: - - 1.1.1.1 - volumes: - - type: bind - source: /srv/sys/ddns-updater - target: /updater/data - - tunnel: - deploy: - replicas: 0 - image: lscr.io/linuxserver/openssh-server - user: abc - entrypoint: - - /usr/bin/ssh - - -N - - -R 172.17.0.1:5880:caddy:80 # 172.17.0.1 = docker host IP - - -R :5822:host.docker.internal:22 - - -o ServerAliveInterval=30 - - core@melville.woozle.org - extra_hosts: - - host.docker.internal:host-gateway - secrets: - - source: tunnel - target: /config/.ssh/id_rsa - uid: "911" - gid: "911" - mode: 0600 - - source: known_hosts - target: /config/.ssh/known_hosts - uid: "911" - gid: "911" - mode: 0600 - - -configs: - dave.yaml: - file: dave.yaml - name: dave.yaml-v3 - Corefile: - file: Corefile - name: Corefile-v3 - Caddyfile: - file: Caddyfile - name: Caddyfile-v89 - index.html: - file: www/index.html - name: index.html-v36 - index.mjs: - file: www/index.mjs - name: index.mjs-v1 - index.css: - file: www/index.css - name: index.css-v1 - browser.html: - file: www/browser.html - name: browser.html-v3 - deergrove.png: - file: www/deergrove.png - name: deergrove.png-v1 - authelia.yaml: - file: authelia.yaml - name: authelia.yaml-v1 - -secrets: - passwd: - file: secrets/passwd - name: passwd-v2 - simpleauth.key: - file: secrets/simpleauth.key - name: simpleauth.key-v1 - tunnel: - file: secrets/tunnel - name: tunnel-v1 - known_hosts: - file: secrets/known_hosts - name: known_hosts-v1 - forgejo.ini: - file: secrets/forgejo.ini - name: forgejo.ini-v1 - jwt.secret: - file: secrets/jwt.secret - name: jwt.secret-v1 - storage.secret: - file: secrets/storage.secret - name: storage.secret-v1 - session.secret: - file: secrets/session.secret - name: session.secret-v1 - users.yaml: - file: secrets/users.yaml - name: users.yaml-v1 - -networks: - hostnet: - external: true - name: host - - diff --git a/homelab/unused/ocis.yaml b/homelab/unused/ocis.yaml deleted file mode 100644 index ada6672..0000000 --- a/homelab/unused/ocis.yaml +++ /dev/null @@ -1,252 +0,0 @@ -version: "3.8" -services: - traefik: - image: traefik - environment: - TRAEFIK_API: "true" - TRAEFIK_API_INSECURE: "true" - TRAEFIK_ENTRYPOINTS_WEB_ADDRESS: :80 - TRAEFIK_ENTRYPOINTS_WEB_HTTP_REDIRECTIONS_ENTRYPOINT_TO: websecure - TRAEFIK_ENTRYPOINTS_WEB_HTTP_REDIRECTIONS_ENTRYPOINT_SCHEME: https - TRAEFIK_ENTRYPOINTS_WEBSECURE_ADDRESS: :443 - TRAEFIK_ENTRYPOINTS_WEBSECURE_HTTP_TLS_CERTRESOLVER: letsencrypt - TRAEFIK_CERTIFICATESRESOLVERS_LETSENCYRPT_ACME_EMAIL: neale@woozle.org - TRAEFIK_CERTIFICATESRESOLVERS_LETSENCRYPT_ACME_STORAGE: /acme.json - XXX_TRAEFIK_CERTIFICATESRESOLVERS_LETSENCRYPT_ACME_HTTPCHALLENGE_ENTRYPOINT: web - TRAEFIK_CERTIFICATESRESOLVERS_LETSENCRYPT_ACME_TLSCHALLENGE: "true" - TRAEFIK_PROVIDERS_DOCKER_SWARMMODE: "true" - TRAEFIK_PROVIDERS_DOCKER_EXPOSEDBYDEFAULT: "false" - ports: - - target: 443 - published: 443 - mode: host - - target: 80 - published: 80 - mode: host - volumes: - - type: bind - source: /var/run/docker.sock - target: /var/run/docker.sock - read_only: true - - type: bind - source: /srv/ext/sys/traefik/acme.json - target: /acme.json - deploy: - labels: - # XXX: This HSTS stuff doesn't seem to be working - traefik.enable: "true" - traefik.frontend.headers.STSSeconds: "31536000" - traefik.frontend.headers.STSPreload: "true" - traefik.http.routers.dashboard.rule: "Host(`$FQDN`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))" - traefik.http.routers.dashboard.tls.certresolver: letsencrypt - traefik.http.routers.dashboard.middlewares: forward-auth - traefik.http.routers.dashboard.service: api@internal - traefik.http.middlewares.forward-auth.forwardauth.address: http://simpleauth:8080/ - traefik.http.services.traefik.loadbalancer.server.port: "1" - - simpleauth: - image: ghcr.io/nealey/simpleauth - secrets: - - password - deploy: - labels: - traefik.enable: "true" - traefik.http.routers.simpleauth.rule: "Host(`$FQDN`) && Path(`/`)" - traefik.http.services.simpleauth.loadbalancer.server.port: "8080" - - plex: - image: ghcr.io/linuxserver/plex - networks: - - hostnet - environment: - TZ: US/Mountain - VERSION: public - volumes: - - type: bind - source: /srv/ext/sys/plex - target: /config - - type: bind - source: /srv - target: /srv - read_only: true - bind: - propagation: rslave - - transmission: - image: ghcr.io/linuxserver/transmission - networks: - - hostnet - volumes: - - type: bind - source: /srv/ext/sys/transmission - target: /config - - type: bind - source: /srv/ext/incoming - target: /srv/ext/incoming - deploy: - labels: - # This isn't going to work, because transmission binds to the host network. - traefik.http.routers.transmission.rule: "PathPrefix(`/transmission`)" - traefik.http.services.transmission.loadbalancer.server.port: "9091" - - ocis: - image: owncloud/ocis:2.0.0-beta.5 - environment: - OCIS_URL: https://drive.woozle.org/ - PROXY_TLS: "false" -# ports: -# - published: 9200 -# target: 9200 - volumes: - - type: bind - source: /srv/ext/sys/ocis/config - target: /etc/ocis - - type: bind - source: /srv/ext/sys/ocis/data - target: /var/lib/ocis - deploy: - labels: - traefik.enable: "true" - traefik.http.routers.ocis.rule: "Host(`drive.woozle.org`)" - traefik.http.routers.ocis.tls: "true" - traefik.http.routers.ocis.tls.certresolver: letsencrypt - traefik.http.services.ocis.loadbalancer.server.port: "9200" - - gitea: - image: gitea/gitea:1 - environment: - USER_UID: 1000 - USER_GID: 1000 - volumes: - - type: bind - source: /srv/ext/sys/gitea - target: /data - - type: bind - source: /etc/timezone - target: /etc/timezone - read_only: true - - type: bind - source: /etc/localtime - target: /etc/localtime - read_only: true - deploy: - labels: - traefik.enable: "true" - traefik.http.routers.gitea.rule: "Host(`git.woozle.org`)" - traefik.http.routers.gitea.middlewares: gitea-striparoo - traefik.http.middlewares.gitea-striparoo.stripprefix.prefixes: "/gitea" - traefik.http.services.gitea.loadbalancer.server.port: "3000" - - atlas: - image: ctassisf/ripe-atlas-alpine:arm64v8 - volumes: - - type: bind - source: /srv/ext/sys/atlas/etc - target: /var/atlas-probe/etc - - type: bind - source: /srv/ext/sys/atlas/status - target: /var/atlas-probe/status - networks: - - hostnet - -## Drop this in to get a netdata container. -## It uses a lot of RAM and causes my machine to swap. -## Granted, it's a lot more lightweight than nextcloud. -## But I can live without netdata. -# netdata: -# image: netdata/netdata -# hostname: $HOSTNAME -# volumes: -# - type: bind -# source: / -# target: /host -# read_only: true -# configs: -# - source: netdata.conf -# target: /etc/netdata/netdata.conf -# deploy: -# labels: -# traefik.http.routers.netdata.rule: "PathPrefix(`/netdata`)" -# traefik.http.middlewares.netdata-striparoo.stripprefix.prefixes: "/netdata" -# traefik.http.routers.netdata.middlewares: netdata-striparoo -# traefik.http.services.netdata.loadbalancer.server.port: "19999" - - geneweb: - image: ravermeister/geneweb - volumes: - - type: bind - source: /srv/ext/sys/geneweb/etc - target: /usr/local/share/geneweb/etc - - type: bind - source: /srv/ext/sys/geneweb/share/data - target: /usr/local/share/geneweb/share/data - - type: bind - source: /srv/ext/sys/geneweb/log - target: /usr/local/share/geneweb/log - deploy: - labels: - traefik.enable: "true" - traefik.http.routers.gwsetup.rule: "PathPrefix(`/gwsetup`)" - traefik.http.middlewares.gwsetup-striparoo.stripprefix.prefixes: "/gwsetup" - traefik.http.routers.gwsetup.middlewares: gwsetup-striparoo,forward-auth - traefik.http.routers.gwsetup.service: gwsetup - traefik.http.services.gwsetup.loadbalancer.server.port: "2316" - - traefik.http.routers.geneweb.rule: "Host(`ancestry.woozle.org`)" - traefik.http.routers.geneweb.service: geneweb - traefik.http.services.geneweb.loadbalancer.server.port: "2317" - - samba: - image: dperson/samba - volumes: - - type: bind - source: /srv/ext - target: /srv/ext - bind: - propagation: rslave - environment: - NMBD: enable - RECYCLE: disable - USERID: 911 - GROUPID: 911 - # name;path;browse;readonly;guest - SHARE1: storage;/srv/ext/storage;yes;no;no - SHARE2: media;/srv/ext/media;yes;no;no - SHARE3: software;/srv/ext/software;yes;no;no - SHARE4: backups;/srv/ext/backups;yes;no;no - SHARE4: incoming;/srv/ext/incoming;yes;no;no - env_file: - - samba-users.env - ports: - - published: 139 - target: 139 - - published: 445 - target: 445 - - public: - image: caddy - volumes: - - type: bind - source: /srv/ext/storage/public - target: /usr/share/caddy/public - read_only: true - deploy: - labels: - traefik.enable: "true" - traefik.http.routers.public.rule: "PathPrefix(`/public`)" - traefik.http.services.public.loadbalancer.server.port: "80" - -configs: - netdata.conf: - file: netdata.conf - name: netdata.conf-v4 - -secrets: - password: - file: password - name: password-v1 - -networks: - hostnet: - external: true - name: host diff --git a/homelab/unused/periodic/backup-systemd b/homelab/unused/periodic/backup-systemd deleted file mode 100755 index b258588..0000000 --- a/homelab/unused/periodic/backup-systemd +++ /dev/null @@ -1,3 +0,0 @@ -#! /bin/sh - -tar czf /mnt/ardenne/backups/sweetums.tar.gz /host/etc/systemd diff --git a/homelab/unused/periodic/btrfs-scrub b/homelab/unused/periodic/btrfs-scrub deleted file mode 100755 index 36913bb..0000000 --- a/homelab/unused/periodic/btrfs-scrub +++ /dev/null @@ -1,9 +0,0 @@ -#! /bin/sh - -# We do this on the host's cron now -exit 0 - -for mnt in /mnt/ardenne; do - chroot /host /usr/bin/btrfs scrub start -B $mnt -done - diff --git a/homelab/unused/periodic/ddns-update b/homelab/unused/periodic/ddns-update deleted file mode 100755 index abbb58c..0000000 --- a/homelab/unused/periodic/ddns-update +++ /dev/null @@ -1,38 +0,0 @@ -#! /bin/sh - -domain=woozle.org -host=sweetums -key=6SRjTBJG7v2bHyG9gqX913w1 - -log() { - echo "=== $*" -} - -json() { - ip4=$1 - ip6=$2 - printf '{"items": [' - if [ -n "$ip6" ]; then - printf '{"rrset_type":"AAAA","rrset_values":["%s"],"rrset_ttl":300},' "$ip6" - fi - printf '{"rrset_type":"A","rrset_values":["%s"],"rrset_ttl":300}' "$ip4" - printf ']}' -} - -push() { - host=$1 - domain=$2 - authh="Authorization: Apikey $key" - log "$host.$domain" - curl -s -H "$authh" -T - https://api.gandi.net/v5/livedns/domains/$domain/records/$host - echo -} - -me4=$(curl -s -4 https://api64.ipify.org/) -me6=$(curl -s -6 https://api64.ipify.org/) - -log "IPv4: $me4" -log "IPv6: $me6" - -json $me4 $me6 | push sweetums woozle.org -json $me4 | push drive woozle.org diff --git a/homelab/unused/periodic/gdrive-backup b/homelab/unused/periodic/gdrive-backup deleted file mode 100755 index fda7fdf..0000000 --- a/homelab/unused/periodic/gdrive-backup +++ /dev/null @@ -1,11 +0,0 @@ -#! /bin/sh -e - -for user in neale amy ginnie; do - dir=/mnt/ext/backups/$user - rclone \ - --config=$dir/rclone.conf \ - --bwlimit=2M \ - --transfers=1 \ - sync gdrive: $dir/gdrive - chown -R $(stat -c %u:%g $dir) $dir -done diff --git a/homelab/unused/periodic/last-run b/homelab/unused/periodic/last-run deleted file mode 100755 index 790e23f..0000000 --- a/homelab/unused/periodic/last-run +++ /dev/null @@ -1,3 +0,0 @@ -#! /bin/sh - -date > /mnt/ext/srv/periodic/last-run diff --git a/homelab/unused/periodic/nextcloud-cron b/homelab/unused/periodic/nextcloud-cron deleted file mode 100755 index 6b65374..0000000 --- a/homelab/unused/periodic/nextcloud-cron +++ /dev/null @@ -1,4 +0,0 @@ -#! /bin/sh - -[ $(hostname) = sweetums ] || exit 0 -wget -O - https://drive.woozle.org/cron.php >/dev/null diff --git a/homelab/unused/prometheus.yaml b/homelab/unused/prometheus.yaml deleted file mode 100644 index eba971e..0000000 --- a/homelab/unused/prometheus.yaml +++ /dev/null @@ -1,7 +0,0 @@ -global: - -scrape_configs: - - job_name: node_exporter - static_configs: - - targets: - - node-exporter:9100 diff --git a/homelab/webfs/finish b/homelab/webfs/finish new file mode 100755 index 0000000..0428209 --- /dev/null +++ b/homelab/webfs/finish @@ -0,0 +1,3 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman stop $me diff --git a/homelab/webfs/run b/homelab/webfs/run new file mode 100755 index 0000000..3bec13f --- /dev/null +++ b/homelab/webfs/run @@ -0,0 +1,11 @@ +#! /bin/sh +me=$(basename $(pwd)) +podman rm $me +podman run \ + --name $me \ + --network homelab \ + --user 911:911 \ + --volume /srv/storage:/srv/storage \ + --volume /srv/incoming:/srv/incoming \ + --volume /srv/media:/srv/media \ + sigoden/dufs -A /srv diff --git a/homelab/www/index.css b/homelab/www/index.css deleted file mode 100644 index fc2f70e..0000000 --- a/homelab/www/index.css +++ /dev/null @@ -1,78 +0,0 @@ -body { - display: flex; - flex-flow: column; - height: 100vh; - margin: 0; - font-family: Helvetica, sans-serif; - background-color: #222; - color: white; -} - -.hidden { - display: none; -} - -nav { - overflow-x: auto; - font-weight: bold; - font-size: 12pt; - display: flex; -} -nav img { - max-height: 2em; -} -nav a { - padding: 0.5em 1.5em; - color: #aaa; - text-decoration: none; - white-space: nowrap; -} -nav a[data-no-menu] { - display: none; -} -nav a:hover { - background: #555; -} -nav a.active { - background: #8b8; - color: black; -} - -#app { - flex-grow: 1; -} -iframe { - display: block; - border: none; - width: 100%; - height: 100%; -} - -.icons { - margin: auto 2em; -} -.icons { - display: flex; - flex-wrap: wrap; - justify-content: center; - max-width: 40em; - margin: auto; - gap: 20px; -} -.icons a { - background-color: #444; - color: #fff; - width: 120px; - height: 120px; - border-radius: 10px; - display: flex; - justify-content: center; - align-items: center; -} -.icons a img { - max-width: 66%; - max-height: 66%; - width: 100%; - height: 100%; - image-rendering: pixelated; -} diff --git a/homelab/www/index.html b/homelab/www/index.html deleted file mode 100644 index cce5201..0000000 --- a/homelab/www/index.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - Deer Grove - - - - - - - - -
- -
- - diff --git a/homelab/www/index.mjs b/homelab/www/index.mjs deleted file mode 100644 index 68b1144..0000000 --- a/homelab/www/index.mjs +++ /dev/null @@ -1,109 +0,0 @@ -let frames = {} -function activate(event, element) { - event.preventDefault() - - let parent = element.parentElement - for (let e of parent.getElementsByClassName("active")) { - e.classList.remove("active") - } - element.classList.add("active") - let href = element.href - let app = document.querySelector("#app") - - let frame = frames[href] - if (frame) { - frame.dispatchEvent(new Event("load")) - } else { - frame = app.appendChild(document.createElement("iframe")) - frame.addEventListener("load", e => frameLoaded(frame)) - frame.src = href - frames[href] = frame - } - - for (let fhref in frames) { - let f = frames[fhref] - if (fhref == href) { - f.classList.remove("hidden") - } else { - f.classList.add("hidden") - } - } -} - - -function frameLoaded(frame) { - let doc = frame.contentDocument - if (doc.title.length > 0) { - document.title = doc.title - } - let icon = document.querySelector("link[rel~='icon']") - let dicon = doc.querySelector("link[rel~='icon']") - if (dicon) { - icon.href = dicon.href - } else { - icon.href = defaultIcon - } -} - -let defaultIcon = null -async function init() { - let doc = document.querySelector("iframe").contentDocument - - defaultIcon = document.querySelector("link[rel~='icon']").href - - for (let l of document.head.querySelectorAll("style")) { - doc.head.appendChild(l.cloneNode(true)) - } - for (let l of document.head.querySelectorAll("link[rel='stylesheet']")) { - doc.head.appendChild(l.cloneNode()) - } - for (let f of document.querySelectorAll("#app iframe")) { - frames[f.src] = f - } - - - let icons = doc.body.appendChild(doc.createElement("section")) - icons.classList.add("icons") - - let portalURL = new URL("portal.json", window.location) - let resp = await fetch(portalURL) - let obj = await resp.json() - let nav = document.querySelector("nav") - for (let app of obj) { - let hlink = null - if (app.target != "_blank") { - hlink = nav.appendChild(document.createElement("a")) - hlink.href = app.href - hlink.textContent = app.title - if (app.target) { - hlink.target = app.target - } else { - hlink.addEventListener("click", event => activate(event, hlink)) - } - } - - let dlink = icons.appendChild(doc.createElement("a")) - dlink.href = app.href - if (app.target) { - dlink.target = app.target - } else { - dlink.addEventListener("click", event => activate(event, hlink)) - } - if (app.icon) { - let icon = dlink.appendChild(doc.createElement("img")) - icon.src = app.icon - icon.alt = app.title - icon.title = app.title - icon.style.objectFit = "cover" - } else { - let text = dlink.appendChild(doc.createElement("div")) - text.textContent = app.title - } - } -} - -if (document.readyState === "loading") { - document.addEventListener("DOMContentLoaded", init) -} else { - init() -}