Initial
This commit is contained in:
commit
9357112dbe
|
@ -0,0 +1,8 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
stack=$(basename $(pwd))
|
||||||
|
|
||||||
|
cat HOSTS | while read host; do
|
||||||
|
echo "=== $host"
|
||||||
|
HOSTNAME=$host docker -H ssh://$host stack deploy -c docker-compose.yaml --prune $stack
|
||||||
|
done
|
|
@ -0,0 +1,11 @@
|
||||||
|
#! /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
|
|
@ -0,0 +1,17 @@
|
||||||
|
version: "3.8"
|
||||||
|
services:
|
||||||
|
cron:
|
||||||
|
image: rclone/rclone
|
||||||
|
configs:
|
||||||
|
- source: backup.sh
|
||||||
|
target: /etc/periodic/daily/gdrive-backup
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: /mnt/
|
||||||
|
target: /mnt/
|
||||||
|
entrypoint: [ "/usr/sbin/crond", "-fd", "8" ]
|
||||||
|
|
||||||
|
configs:
|
||||||
|
backup.sh:
|
||||||
|
file: backup.sh
|
||||||
|
name: backup.sh-v1
|
|
@ -0,0 +1 @@
|
||||||
|
sweetums.woozle.org
|
|
@ -0,0 +1,14 @@
|
||||||
|
# Authentication
|
||||||
|
|
||||||
|
Grafana is exposed to the world. Let's hope that's safe.
|
||||||
|
Its auth has this nice property that if you send basic-auth creds,
|
||||||
|
it'll use that instead of presenting a login screen.
|
||||||
|
|
||||||
|
Things using basic authentication:
|
||||||
|
* traefik dashboard
|
||||||
|
|
||||||
|
Things using traefik forward-authentication to grafana (you have to log in to grafana first):
|
||||||
|
* prometheus
|
||||||
|
* transmission
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
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: /mnt/ext/srv/traefik/acme.json
|
||||||
|
target: /acme.json
|
||||||
|
secrets:
|
||||||
|
- htaccess
|
||||||
|
deploy:
|
||||||
|
labels:
|
||||||
|
traefik.enable: "true"
|
||||||
|
# XXX: This HSTS stuff doesn't seem to be working
|
||||||
|
traefik.frontend.headers.STSSeconds: "31536000"
|
||||||
|
traefik.frontend.headers.STSPreload: "true"
|
||||||
|
traefik.http.routers.dashboard.rule: "Host(`$HOSTNAME`) && (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.basic-auth.basicauth.usersfile: /run/secrets/htaccess
|
||||||
|
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: "PathPrefix(`/`)"
|
||||||
|
traefik.http.services.simpleauth.loadbalancer.server.port: "8080"
|
||||||
|
plex:
|
||||||
|
image: ghcr.io/linuxserver/plex:1.25.1
|
||||||
|
networks:
|
||||||
|
- hostnet
|
||||||
|
environment:
|
||||||
|
TZ: US/Mountain
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: /mnt/ext/srv/plex
|
||||||
|
target: /config
|
||||||
|
- type: bind
|
||||||
|
source: /media
|
||||||
|
target: /media
|
||||||
|
bind:
|
||||||
|
propagation: rslave
|
||||||
|
transmission:
|
||||||
|
image: ghcr.io/linuxserver/transmission
|
||||||
|
networks:
|
||||||
|
- hostnet
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: /mnt/ext/srv/transmission
|
||||||
|
target: /config
|
||||||
|
- type: bind
|
||||||
|
source: /mnt/ext/torrents
|
||||||
|
target: /mnt/ext/torrents
|
||||||
|
deploy:
|
||||||
|
labels:
|
||||||
|
traefik.enable: "true"
|
||||||
|
traefik.http.routers.transmission.rule: "PathPrefix(`/transmission`)"
|
||||||
|
traefik.http.routers.transmission.tls: "true"
|
||||||
|
traefik.http.routers.transmission.middlewares: forward-auth
|
||||||
|
traefik.http.services.transmission.loadbalancer.server.port: "9091"
|
||||||
|
nextcloud:
|
||||||
|
image: ghcr.io/linuxserver/nextcloud:23.0.0
|
||||||
|
environment:
|
||||||
|
OVERWRITEPROTOCOL: https
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: /mnt/ext/srv/nextcloud
|
||||||
|
target: /config
|
||||||
|
- type: bind
|
||||||
|
source: /mnt/ext/storage
|
||||||
|
target: /data
|
||||||
|
- type: bind
|
||||||
|
source: /mnt/ext
|
||||||
|
target: /mnt/ext
|
||||||
|
read_only: true
|
||||||
|
bind:
|
||||||
|
propagation: rslave
|
||||||
|
deploy:
|
||||||
|
labels:
|
||||||
|
traefik.enable: "true"
|
||||||
|
traefik.http.routers.nextcloud.rule: "Host(`drive.woozle.org`) || PathPrefix(`/nextcloud`)"
|
||||||
|
traefik.http.routers.nextcloud.tls: "true"
|
||||||
|
traefik.http.routers.nextcloud.tls.certresolver: letsencrypt
|
||||||
|
traefik.http.routers.nextcloud.middlewares: nextcloud-caldav@docker
|
||||||
|
traefik.http.middlewares.nextcloud-caldav.redirectregex.permanent: "true"
|
||||||
|
traefik.http.middlewares.nextcloud-caldav.redirectregex.regex: ^https://(.*)/.well-known/(card|cal)dav
|
||||||
|
traefik.http.middlewares.nextcloud-caldav.redirectregex.replacement: https://$${1}/remote.php/dav/
|
||||||
|
traefik.http.services.nextcloud.loadbalancer.server.port: "80"
|
||||||
|
redis:
|
||||||
|
image: redis
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: /mnt/ext/srv/redis
|
||||||
|
target: /var/lib/redis
|
||||||
|
|
||||||
|
secrets:
|
||||||
|
htaccess:
|
||||||
|
file: htaccess
|
||||||
|
name: htaccess-v3
|
||||||
|
password:
|
||||||
|
file: password
|
||||||
|
name: password-v1
|
||||||
|
|
||||||
|
networks:
|
||||||
|
hostnet:
|
||||||
|
external: true
|
||||||
|
name: host
|
|
@ -0,0 +1,10 @@
|
||||||
|
[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
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
tar czf /mnt/ardenne/backups/sweetums.tar.gz /host/etc/systemd
|
|
@ -0,0 +1,9 @@
|
||||||
|
#! /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
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
#! /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
|
|
@ -0,0 +1,11 @@
|
||||||
|
#! /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
|
|
@ -0,0 +1,3 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
date > /mnt/ext/srv/periodic/last-run
|
|
@ -0,0 +1,4 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
[ $(hostname) = sweetums ] || exit 0
|
||||||
|
wget -O - https://drive.woozle.org/cron.php >/dev/null
|
|
@ -0,0 +1,7 @@
|
||||||
|
global:
|
||||||
|
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: node_exporter
|
||||||
|
static_configs:
|
||||||
|
- targets:
|
||||||
|
- node-exporter:9100
|
|
@ -0,0 +1 @@
|
||||||
|
melville.woozle.org
|
|
@ -0,0 +1,74 @@
|
||||||
|
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
|
||||||
|
TRAEFIK_CERTIFICATESRESOLVERS_LETSENCRYPT_ACME_HTTPCHALLENGE_ENTRYPOINT: web
|
||||||
|
TRAEFIK_PROVIDERS_DOCKER_SWARMMODE: "true"
|
||||||
|
TRAEFIK_PROVIDERS_DOCKER_EXPOSEDBYDEFAULT: "false"
|
||||||
|
ports:
|
||||||
|
- target: 80
|
||||||
|
published: 80
|
||||||
|
mode: host
|
||||||
|
- target: 443
|
||||||
|
published: 443
|
||||||
|
mode: host
|
||||||
|
- target: 8080
|
||||||
|
published: 8080
|
||||||
|
volumes:
|
||||||
|
- type: bind
|
||||||
|
source: /var/run/docker.sock
|
||||||
|
target: /var/run/docker.sock
|
||||||
|
read_only: true
|
||||||
|
- type: bind
|
||||||
|
source: /srv/traefik/acme.json
|
||||||
|
target: /acme.json
|
||||||
|
secrets:
|
||||||
|
- htaccess
|
||||||
|
deploy:
|
||||||
|
labels:
|
||||||
|
traefik.enable: "true"
|
||||||
|
traefik.http.routers.dashboard.rule: "Host(`melville.woozle.org`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))"
|
||||||
|
traefik.http.routers.dashboard.tls.certresolver: letsencrypt
|
||||||
|
traefik.http.routers.dashboard.middlewares: auth
|
||||||
|
traefik.http.routers.dashboard.service: api@internal
|
||||||
|
traefik.http.middlewares.auth.basicauth.usersfile: /run/secrets/htaccess
|
||||||
|
traefik.http.services.traefik.loadbalancer.server.port: "1"
|
||||||
|
|
||||||
|
vail:
|
||||||
|
image: ghcr.io/nealey/vail:master
|
||||||
|
deploy:
|
||||||
|
labels:
|
||||||
|
traefik.enable: "true"
|
||||||
|
traefik.http.routers.vail.rule: "PathPrefix(`/vail`) || Host(`vail.woozle.org`)"
|
||||||
|
traefik.http.services.vail.loadbalancer.server.port: "8080"
|
||||||
|
|
||||||
|
chat:
|
||||||
|
image: ghcr.io/dirtbags/microchat
|
||||||
|
command:
|
||||||
|
- --redis=redis:6379
|
||||||
|
- --noauth
|
||||||
|
deploy:
|
||||||
|
labels:
|
||||||
|
traefik.enable: "true"
|
||||||
|
traefik.http.routers.chat.rule: "Host(`melville.woozle.org`) && PathPrefix(`/chat`)"
|
||||||
|
traefik.http.routers.chat.middlewares: chat-prefix
|
||||||
|
traefik.http.middlewares.chat-prefix.stripprefix.prefixes: "/chat"
|
||||||
|
traefik.http.services.chat.loadbalancer.server.port: "8080"
|
||||||
|
redis:
|
||||||
|
image: redis
|
||||||
|
|
||||||
|
|
||||||
|
secrets:
|
||||||
|
htaccess:
|
||||||
|
file: htaccess
|
||||||
|
name: htaccess-v1
|
|
@ -0,0 +1 @@
|
||||||
|
user:$apr1$tIOiVTs2$vDOzHYgsomLL5aCvAinUs1
|
Loading…
Reference in New Issue