Compare commits
36 commits
forwardedf
...
master
Author | SHA1 | Date | |
---|---|---|---|
abd649a1ec | |||
4c7a21418d | |||
a476680b82 | |||
1acb61716e | |||
c7ddefaa3d | |||
833b1a2b5e | |||
44e3bd6729 | |||
59db3b2fb7 | |||
84521ec8a9 | |||
60c4f17219 | |||
db38d9c6bb | |||
c59dcbeaae | |||
6b126e3baa | |||
689fbd3986 | |||
5253c66b1c | |||
5db9f9f254 | |||
ccd1343798 | |||
e4fec5dd4e | |||
cfa1a623c0 | |||
8398975132 | |||
8d1fdc443b | |||
06c3fc56ab | |||
a7872afdd8 | |||
1a745bfa22 | |||
3c4f505413 | |||
af2ee0a076 | |||
056bfafcd5 | |||
8532135054 | |||
251399887b | |||
882578e838 | |||
dad67c8731 | |||
b40c6ca579 | |||
5bb39c4491 | |||
9a4a00c4e7 | |||
3887b9979b | |||
1a527394b3 |
37 changed files with 664 additions and 141 deletions
1
.envrc
Normal file
1
.envrc
Normal file
|
@ -0,0 +1 @@
|
|||
use flake
|
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
.direnv
|
|
@ -1,4 +1,6 @@
|
|||
# shoarma
|
||||
|
||||
⚠️ Code in this repository has been assimilated by the [home/nixos-servers](https://git.kun.is/home/nixos-servers/src/branch/master/legacy) repository.
|
||||
|
||||
Docker Swarm for our home servers.
|
||||
Includes both Terraform and Ansible code to provision and configure the swarm.
|
||||
|
|
|
@ -3,7 +3,7 @@ roles_path=~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles:roles
|
|||
inventory=inventory
|
||||
interpreter_python=/usr/bin/python3
|
||||
remote_user = root
|
||||
vault_password_file=util/secret-service-client.sh
|
||||
vault_password_file=$HOME/.config/home/ansible-vault-secret
|
||||
|
||||
[diff]
|
||||
always = True
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
data_directory_base: /mnt/data
|
||||
git_ssh_port: 56287
|
||||
elasticsearch_port: 14653
|
||||
fluent_forward_port: 24224
|
||||
concourse_public_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBSVLcr617iJt+hqLFSsOQy1JeueLIAj1eRfuI+KeZAu pim@x260"
|
||||
|
||||
nfs_shares:
|
||||
- name: nextcloud_data
|
||||
|
@ -34,6 +37,22 @@ nfs_shares:
|
|||
path: /mnt/data/overleaf/redis
|
||||
- name: overleaf_mongodb
|
||||
path: /mnt/data/overleaf/mongodb
|
||||
- name: prometheus_data
|
||||
path: /mnt/data/prometheus/data
|
||||
- name: elasticsearch_certs
|
||||
path: /mnt/data/elasticsearch/certs
|
||||
- name: elasticsearch_data
|
||||
path: /mnt/data/elasticsearch/data
|
||||
- name: grafana_data
|
||||
path: /mnt/data/grafana/data
|
||||
- name: kitchenowl_data
|
||||
path: /mnt/data/kitchenowl/data
|
||||
- name: ampache_mysql
|
||||
path: /mnt/data/ampache/mysql
|
||||
- name: ampache_config
|
||||
path: /mnt/data/ampache/config
|
||||
- name: music
|
||||
path: /mnt/data/nextcloud/data/data/pim/files/Music
|
||||
|
||||
database_passwords:
|
||||
nextcloud: !vault |
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
docker_node_labels:
|
||||
- hostname: maestro
|
||||
labels: {}
|
||||
- hostname: swarmpub1
|
||||
labels:
|
||||
public: "true"
|
||||
mastodon: "true"
|
||||
- hostname: swarmpub2
|
||||
labels:
|
||||
public: "true"
|
||||
jitsi: "true"
|
||||
- hostname: swarmpriv1
|
||||
labels:
|
||||
private: "true"
|
||||
overleaf: "true"
|
||||
syncthing: "true"
|
||||
hedgedoc: "true"
|
||||
radicale: "true"
|
||||
- hostname: swarmpriv2
|
||||
labels:
|
||||
private: "true"
|
||||
seafile: "true"
|
||||
freshrss: "true"
|
||||
pihole: "true"
|
||||
discourse: "true"
|
|
@ -7,11 +7,7 @@ all:
|
|||
children:
|
||||
workers:
|
||||
hosts:
|
||||
swarmpub1:
|
||||
ansible_host: swarmpub1.dmz
|
||||
swarmpub2:
|
||||
ansible_host: swarmpub2.dmz
|
||||
swarmpriv1:
|
||||
ansible_host: swarmpriv1.dmz
|
||||
swarmpriv2:
|
||||
ansible_host: swarmpriv2.dmz
|
||||
bancomart:
|
||||
ansible_host: bancomart.dmz
|
||||
vpay:
|
||||
ansible_host: vpay.dmz
|
||||
|
|
9
ansible/playbooks/remove_stack.yml
Normal file
9
ansible/playbooks/remove_stack.yml
Normal file
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
- name: Remove a Docker swarm stack
|
||||
hosts: manager
|
||||
|
||||
tasks:
|
||||
- name: Remove the stack
|
||||
docker_stack:
|
||||
name: "{{ stack }}"
|
||||
state: absent
|
|
@ -17,7 +17,17 @@
|
|||
|
||||
roles:
|
||||
- setup_apt
|
||||
- docker
|
||||
|
||||
post_tasks:
|
||||
- name: Install Docker
|
||||
include_role:
|
||||
name: docker
|
||||
vars:
|
||||
docker_daemon_config: {}
|
||||
# log-driver: fluentd
|
||||
# log-opts:
|
||||
# fluentd-address: "localhost:22222"
|
||||
# tag: "docker.{{ '{{' }}.Name{{ '}}' }}"
|
||||
|
||||
- name: Setup Docker Swarm manager
|
||||
hosts: manager
|
||||
|
@ -49,9 +59,14 @@
|
|||
|
||||
- hosts: manager
|
||||
tasks:
|
||||
- name: Add labels to Docker Swarm
|
||||
docker_node:
|
||||
hostname: "{{ item.hostname }}"
|
||||
labels: "{{ item.labels }}"
|
||||
labels_state: replace
|
||||
loop: "{{ docker_node_labels }}"
|
||||
- name: Add concourse to authorized keys
|
||||
authorized_key:
|
||||
user: root
|
||||
key: "{{ concourse_public_key }}"
|
||||
|
||||
- hosts: manager, workers
|
||||
tasks:
|
||||
- name: Increase vm.max_map_count
|
||||
sysctl:
|
||||
name: vm.max_map_count
|
||||
value: 262144
|
||||
|
|
|
@ -9,13 +9,15 @@
|
|||
- {role: mastodon, tags: mastodon}
|
||||
- {role: freshrss, tags: freshrss}
|
||||
- {role: hedgedoc, tags: hedgedoc}
|
||||
- {role: overleaf, tags: overleaf}
|
||||
# - {role: overleaf, tags: overleaf}
|
||||
- {role: cyberchef, tags: cyberchef}
|
||||
- {role: inbucket, tags: inbucket}
|
||||
- {role: kms, tags: kms}
|
||||
- {role: swarm_dashboard, tags: swarm_dashboard}
|
||||
- {role: shephard, tags: shephard}
|
||||
# - {role: jitsi, tags: jitsi}
|
||||
- {role: pihole, tags: pihole}
|
||||
- {role: nextcloud, tags: nextcloud}
|
||||
- {role: syncthing, tags: syncthing}
|
||||
- {role: monitoring, tags: monitoring}
|
||||
- {role: kitchenowl, tags: kitchenowl}
|
||||
- {role: ampache, tags: ampache}
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
- name: setup_apt
|
||||
src: https://github.com/sunscrapers/ansible-role-apt.git
|
||||
scm: git
|
||||
- name: docker
|
||||
src: https://git.kun.is/pim/ansible-role-docker
|
||||
scm: git
|
||||
- name: cloudinit_wait
|
||||
src: https://git.kun.is/pim/ansible-role-cloudinit-wait
|
||||
scm: git
|
||||
- name: postgresql_database
|
||||
src: https://git.kun.is/home/ansible-role-postgresql-database
|
||||
scm: git
|
||||
---
|
||||
roles:
|
||||
- name: setup_apt
|
||||
src: https://github.com/sunscrapers/ansible-role-apt.git
|
||||
scm: git
|
||||
- name: docker
|
||||
src: https://git.kun.is/pim/ansible-role-docker
|
||||
scm: git
|
||||
- name: cloudinit_wait
|
||||
src: https://git.kun.is/pim/ansible-role-cloudinit-wait
|
||||
scm: git
|
||||
- name: postgresql_database
|
||||
src: https://git.kun.is/home/ansible-role-postgresql-database
|
||||
scm: git
|
||||
|
|
56
ansible/roles/ampache/docker-stack.yml.j2
Normal file
56
ansible/roles/ampache/docker-stack.yml.j2
Normal file
|
@ -0,0 +1,56 @@
|
|||
# vi: ft=yaml
|
||||
version: '3.7'
|
||||
|
||||
networks:
|
||||
traefik:
|
||||
external: true
|
||||
|
||||
volumes:
|
||||
ampache_mysql:
|
||||
driver_opts:
|
||||
type: "nfs"
|
||||
o: "addr=192.168.30.10,nolock,soft,rw"
|
||||
device: ":/mnt/data/ampache/mysql"
|
||||
ampache_config:
|
||||
driver_opts:
|
||||
type: "nfs"
|
||||
o: "addr=192.168.30.10,nolock,soft,rw"
|
||||
device: ":/mnt/data/ampache/config"
|
||||
music:
|
||||
driver_opts:
|
||||
type: "nfs"
|
||||
o: "addr=192.168.30.10,nolock,soft,rw"
|
||||
device: ":/mnt/data/nextcloud/data/data/pim/files/Music"
|
||||
|
||||
services:
|
||||
ampache:
|
||||
image: ampache/ampache:6
|
||||
volumes:
|
||||
- type: volume
|
||||
source: ampache_mysql
|
||||
target: /var/lib/mysql
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: ampache_config
|
||||
target: /var/www/config
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: music
|
||||
target: /media
|
||||
read_only: true
|
||||
volume:
|
||||
nocopy: true
|
||||
networks:
|
||||
- traefik
|
||||
deploy:
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.ampache.entrypoints=websecure
|
||||
- traefik.http.routers.ampache.rule=Host(`music.kun.is`)
|
||||
- traefik.http.routers.ampache.tls=true
|
||||
- traefik.http.routers.ampache.tls.certresolver=letsencrypt
|
||||
- traefik.http.routers.ampache.service=ampache
|
||||
- traefik.http.services.ampache.loadbalancer.server.port=80
|
||||
- traefik.docker.network=traefik
|
5
ansible/roles/ampache/tasks/main.yml
Normal file
5
ansible/roles/ampache/tasks/main.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
- name: Deploy Docker stack
|
||||
docker_stack:
|
||||
name: ampache
|
||||
compose:
|
||||
- "{{ lookup('template', '{{ role_path }}/docker-stack.yml.j2') | from_yaml }}"
|
|
@ -1,6 +1,7 @@
|
|||
APP_NAME = Forgejo: Beyond coding. We forge.
|
||||
RUN_MODE = prod
|
||||
RUN_USER = git
|
||||
WORK_PATH=/data/gitea
|
||||
|
||||
[repository]
|
||||
ROOT = /data/git/repositories
|
||||
|
@ -56,8 +57,9 @@ PATH = /data/gitea/attachments
|
|||
[log]
|
||||
MODE = console
|
||||
LEVEL = info
|
||||
ROUTER = console
|
||||
logger.router.MODE = console
|
||||
ROOT_PATH = /data/gitea/log
|
||||
logger.access.MODE=console
|
||||
|
||||
[security]
|
||||
INSTALL_LOCK = true
|
||||
|
@ -102,3 +104,6 @@ DEFAULT_TRUST_MODEL = committer
|
|||
|
||||
[ui]
|
||||
DEFAULT_THEME = forgejo-light
|
||||
|
||||
[oauth2]
|
||||
ENABLE=false
|
||||
|
|
|
@ -18,8 +18,8 @@ volumes:
|
|||
device: ":/mnt/data/forgejo"
|
||||
|
||||
services:
|
||||
server:
|
||||
image: codeberg.org/forgejo/forgejo:1.18
|
||||
forgejo:
|
||||
image: codeberg.org/forgejo/forgejo:1.20
|
||||
environment:
|
||||
- USER_UID=1000
|
||||
- USER_GID=1000
|
||||
|
@ -49,6 +49,8 @@ services:
|
|||
- traefik.http.routers.forgejo.service=forgejo
|
||||
- traefik.http.services.forgejo.loadbalancer.server.port=3000
|
||||
- traefik.docker.network=traefik
|
||||
- traefik.http.middlewares.set-forwarded-for.headers.hostsProxyHeaders=X-Forwarded-For
|
||||
- traefik.http.routers.forgejo.middlewares=set-forwarded-for
|
||||
configs:
|
||||
- source: config
|
||||
target: /data/gitea/conf/app.ini
|
||||
|
|
|
@ -13,7 +13,7 @@ volumes:
|
|||
device: ":/mnt/data/hedgedoc/uploads"
|
||||
|
||||
services:
|
||||
hedgedoc-app:
|
||||
hedgedoc:
|
||||
image: quay.io/hedgedoc/hedgedoc:1.9.7
|
||||
environment:
|
||||
- CMD_DB_URL=postgres://hedgedoc:{{ database_passwords.hedgedoc }}@192.168.30.10:5432/hedgedoc
|
||||
|
|
|
@ -6,7 +6,7 @@ networks:
|
|||
external: true
|
||||
|
||||
services:
|
||||
kms-server:
|
||||
inbucket:
|
||||
image: inbucket/inbucket
|
||||
networks:
|
||||
- traefik
|
||||
|
|
45
ansible/roles/kitchenowl/docker-stack.yml.j2
Normal file
45
ansible/roles/kitchenowl/docker-stack.yml.j2
Normal file
|
@ -0,0 +1,45 @@
|
|||
# vi: ft=yaml
|
||||
version: '3.7'
|
||||
|
||||
networks:
|
||||
traefik:
|
||||
external: true
|
||||
kitchenowl:
|
||||
|
||||
volumes:
|
||||
data:
|
||||
driver_opts:
|
||||
type: "nfs"
|
||||
o: "addr=192.168.30.10,nolock,soft,rw"
|
||||
device: ":/mnt/data/kitchenowl/data"
|
||||
|
||||
services:
|
||||
front:
|
||||
image: tombursch/kitchenowl-web:v0.4.17
|
||||
depends_on:
|
||||
- back
|
||||
networks:
|
||||
- traefik
|
||||
- kitchenowl
|
||||
deploy:
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.kitchenowl.entrypoints=websecure
|
||||
- traefik.http.routers.kitchenowl.rule=Host(`boodschappen.kun.is`)
|
||||
- traefik.http.routers.kitchenowl.tls=true
|
||||
- traefik.http.routers.kitchenowl.tls.certresolver=letsencrypt
|
||||
- traefik.http.routers.kitchenowl.service=kitchenowl
|
||||
- traefik.http.services.kitchenowl.loadbalancer.server.port=80
|
||||
- traefik.docker.network=traefik
|
||||
back:
|
||||
image: tombursch/kitchenowl:v88
|
||||
networks:
|
||||
- kitchenowl
|
||||
environment:
|
||||
- JWT_SECRET_KEY={{ jwt_secret_key }}
|
||||
volumes:
|
||||
- type: volume
|
||||
source: data
|
||||
target: /data
|
||||
volume:
|
||||
nocopy: true
|
5
ansible/roles/kitchenowl/tasks/main.yml
Normal file
5
ansible/roles/kitchenowl/tasks/main.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
- name: Deploy Docker stack
|
||||
docker_stack:
|
||||
name: kitchenowl
|
||||
compose:
|
||||
- "{{ lookup('template', '{{ role_path }}/docker-stack.yml.j2') | from_yaml }}"
|
7
ansible/roles/kitchenowl/vars/main.yml
Normal file
7
ansible/roles/kitchenowl/vars/main.yml
Normal file
|
@ -0,0 +1,7 @@
|
|||
jwt_secret_key: !vault |
|
||||
$ANSIBLE_VAULT;1.1;AES256
|
||||
37376338663532376135613331303737626633666138643132316336306164393134633639303865
|
||||
3134613830323335663466373262316262353464323535300a636163633439323035643033623363
|
||||
36316361656133663235333834343233363134313938656664356538366166653336656562623664
|
||||
3332393330616636630a646139393937313932373963623764346134323635336539346562346635
|
||||
36613637396133383664323561666464346336386233363434653765356334633831
|
|
@ -2,7 +2,7 @@
|
|||
version: '3.7'
|
||||
|
||||
services:
|
||||
kms-server:
|
||||
kms:
|
||||
image: teddysun/kms
|
||||
ports:
|
||||
- 1688:1688
|
||||
|
|
132
ansible/roles/monitoring/docker-stack.yml.j2
Normal file
132
ansible/roles/monitoring/docker-stack.yml.j2
Normal file
|
@ -0,0 +1,132 @@
|
|||
# vi: ft=yaml
|
||||
version: "3.8"
|
||||
|
||||
networks:
|
||||
traefik:
|
||||
external: true
|
||||
grafana:
|
||||
|
||||
configs:
|
||||
esdatasource:
|
||||
external: true
|
||||
name: "{{ esdatasource.config_name }}"
|
||||
fluentconf:
|
||||
external: true
|
||||
name: "{{ fluentconf.config_name }}"
|
||||
|
||||
volumes:
|
||||
escerts:
|
||||
driver_opts:
|
||||
type: "nfs"
|
||||
o: "addr=192.168.30.10,nolock,soft,rw"
|
||||
device: ":/mnt/data/elasticsearch/certs"
|
||||
esdata:
|
||||
driver_opts:
|
||||
type: "nfs"
|
||||
o: "addr=192.168.30.10,nolock,soft,rw"
|
||||
device: ":/mnt/data/elasticsearch/data"
|
||||
grafanadata:
|
||||
driver_opts:
|
||||
type: "nfs"
|
||||
o: "addr=192.168.30.10,nolock,soft,rw"
|
||||
device: ":/mnt/data/grafana/data"
|
||||
|
||||
services:
|
||||
elasticsearch:
|
||||
image: docker.elastic.co/elasticsearch/elasticsearch:8.8.1
|
||||
volumes:
|
||||
- type: volume
|
||||
source: escerts
|
||||
target: /usr/share/elasticsearch/config/certs
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: esdata
|
||||
target: /usr/share/elasticsearch/data
|
||||
volume:
|
||||
nocopy: true
|
||||
ports:
|
||||
- {{ elasticsearch_port }}:9200
|
||||
environment:
|
||||
- node.name=es01
|
||||
- cluster.name=shoarma
|
||||
- discovery.type=single-node
|
||||
- bootstrap.memory_lock=true
|
||||
- xpack.security.enabled=false
|
||||
- xpack.security.http.ssl.enabled=false
|
||||
- xpack.security.http.ssl.key=certs/es01/es01.key
|
||||
- xpack.security.http.ssl.certificate=certs/es01/es01.crt
|
||||
- xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
|
||||
- xpack.security.transport.ssl.enabled=false
|
||||
- xpack.security.transport.ssl.key=certs/es01/es01.key
|
||||
- xpack.security.transport.ssl.certificate=certs/es01/es01.crt
|
||||
- xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt
|
||||
- xpack.security.transport.ssl.verification_mode=certificate
|
||||
- xpack.license.self_generated.type=basic
|
||||
ulimits:
|
||||
memlock:
|
||||
soft: -1
|
||||
hard: -1
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"curl http://localhost:9200 | grep -q 'You Know, for Search'",
|
||||
]
|
||||
interval: 10s
|
||||
timeout: 10s
|
||||
retries: 120
|
||||
|
||||
grafana:
|
||||
image: grafana/grafana-oss
|
||||
depends_on:
|
||||
- elasticsearch
|
||||
networks:
|
||||
- traefik
|
||||
- grafana
|
||||
deploy:
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.grafana.entrypoints=localsecure
|
||||
- traefik.http.routers.grafana.rule=Host(`grafana.kun.is`)
|
||||
- traefik.http.routers.grafana.tls=true
|
||||
- traefik.http.routers.grafana.tls.certresolver=letsencrypt
|
||||
- traefik.http.routers.grafana.service=grafana
|
||||
- traefik.http.services.grafana.loadbalancer.server.port=3000
|
||||
- traefik.docker.network=traefik
|
||||
volumes:
|
||||
- type: volume
|
||||
source: grafanadata
|
||||
target: /var/lib/grafana
|
||||
volume:
|
||||
nocopy: true
|
||||
configs:
|
||||
- source: esdatasource
|
||||
target: /etc/grafana/provisioning/datasources/elasticsearch.yaml
|
||||
|
||||
grafana-ntfy:
|
||||
image: kittyandrew/grafana-to-ntfy:master
|
||||
depends_on:
|
||||
- grafana
|
||||
ports:
|
||||
- 8080:8080
|
||||
networks:
|
||||
grafana:
|
||||
aliases:
|
||||
- grafana-ntfy
|
||||
environment:
|
||||
- NTFY_URL=https://ntfy.kun.is/alerts
|
||||
- NTFY_BAUTH_USER=pim
|
||||
- NTFY_BAUTH_PASS={{ ntfy_password }}
|
||||
- BAUTH_USER=admin
|
||||
- BAUTH_PASS=test
|
||||
|
||||
fluentd:
|
||||
image: git.kun.is/pim/fluentd:1.0.3
|
||||
depends_on:
|
||||
- elasticsearch
|
||||
ports:
|
||||
- {{ fluent_forward_port }}:24224
|
||||
configs:
|
||||
- source: fluentconf
|
||||
target: /fluentd/etc/fluent.conf
|
35
ansible/roles/monitoring/elasticsearch.yml.j2
Normal file
35
ansible/roles/monitoring/elasticsearch.yml.j2
Normal file
|
@ -0,0 +1,35 @@
|
|||
# vi: ft=yaml
|
||||
apiVersion: 1
|
||||
|
||||
datasources:
|
||||
- name: cpu
|
||||
type: elasticsearch
|
||||
access: proxy
|
||||
url: http://maestro.dmz:{{ elasticsearch_port }}
|
||||
jsonData:
|
||||
index: 'fluentd.cpu-*'
|
||||
timeField: '@timestamp'
|
||||
|
||||
- name: memory
|
||||
type: elasticsearch
|
||||
access: proxy
|
||||
url: http://maestro.dmz:{{ elasticsearch_port }}
|
||||
jsonData:
|
||||
index: 'fluentd.memory-*'
|
||||
timeField: '@timestamp'
|
||||
|
||||
- name: diskfree
|
||||
type: elasticsearch
|
||||
access: proxy
|
||||
url: http://maestro.dmz:{{ elasticsearch_port }}
|
||||
jsonData:
|
||||
index: 'fluentd.diskfree-*'
|
||||
timeField: '@timestamp'
|
||||
|
||||
- name: traefik_access
|
||||
type: elasticsearch
|
||||
access: proxy
|
||||
url: http://maestro.dmz:{{ elasticsearch_port }}
|
||||
jsonData:
|
||||
index: 'fluentd.access.traefik-*'
|
||||
timeField: '@timestamp'
|
35
ansible/roles/monitoring/fluent.conf.j2
Normal file
35
ansible/roles/monitoring/fluent.conf.j2
Normal file
|
@ -0,0 +1,35 @@
|
|||
# vi: ft=yaml
|
||||
# Receive events from 24224/tcp
|
||||
# This is used by log forwarding and the fluent-cat command
|
||||
<source>
|
||||
@type forward
|
||||
port {{ fluent_forward_port }}
|
||||
</source>
|
||||
|
||||
<filter access.**>
|
||||
@type geoip
|
||||
geoip_lookup_keys host
|
||||
backend_library geoip2_c
|
||||
<record>
|
||||
latitude ${location.latitude["host"]}
|
||||
longitude ${location.longitude["host"]}
|
||||
</record>
|
||||
skip_adding_null_record true
|
||||
</filter>
|
||||
|
||||
<match cpu memory diskfree access.**>
|
||||
@type elasticsearch
|
||||
host maestro.dmz
|
||||
port {{ elasticsearch_port }}
|
||||
include_timestamp true
|
||||
logstash_format true
|
||||
logstash_prefix fluentd.${tag}
|
||||
</match>
|
||||
|
||||
<match **>
|
||||
@type null
|
||||
</match>
|
||||
|
||||
<system>
|
||||
log_level info
|
||||
</system>
|
21
ansible/roles/monitoring/tasks/main.yml
Normal file
21
ansible/roles/monitoring/tasks/main.yml
Normal file
|
@ -0,0 +1,21 @@
|
|||
- name: Create fluentd config
|
||||
docker_config:
|
||||
name: fluentconf
|
||||
data: "{{ lookup('template', '{{ role_path }}/fluent.conf.j2') }}"
|
||||
use_ssh_client: true
|
||||
rolling_versions: true
|
||||
register: fluentconf
|
||||
|
||||
- name: Create elasticsearch data source config
|
||||
docker_config:
|
||||
name: esdatasource
|
||||
data: "{{ lookup('template', '{{ role_path }}/elasticsearch.yml.j2') }}"
|
||||
use_ssh_client: true
|
||||
rolling_versions: true
|
||||
register: esdatasource
|
||||
|
||||
- name: Deploy Docker stack
|
||||
docker_stack:
|
||||
name: monitoring
|
||||
compose:
|
||||
- "{{ lookup('template', '{{ role_path }}/docker-stack.yml.j2') | from_yaml }}"
|
8
ansible/roles/monitoring/vars/main.yml
Normal file
8
ansible/roles/monitoring/vars/main.yml
Normal file
|
@ -0,0 +1,8 @@
|
|||
ntfy_password: !vault |
|
||||
$ANSIBLE_VAULT;1.1;AES256
|
||||
36333232393635383732336630626463633038353862333430396437333733376239343531663339
|
||||
6364643930636566326463393963316263323061613032350a383930376537373437633333623639
|
||||
66613439636531393761366534333134383231303637643063633537393535356536636530666665
|
||||
6537653731666130610a346135373562333931646237396233613065353165623336373935386137
|
||||
36313830623931313238333430346238626562353661616465333736346230396162386137363435
|
||||
3362636565336639643832626165613236643466633537633236
|
|
@ -13,7 +13,7 @@ volumes:
|
|||
device: ":/mnt/data/nextcloud/data"
|
||||
|
||||
services:
|
||||
app:
|
||||
nextcloud:
|
||||
image: nextcloud:27
|
||||
volumes:
|
||||
- type: volume
|
||||
|
|
|
@ -51,6 +51,7 @@ services:
|
|||
- traefik.http.routers.pihole.tls.certresolver=letsencrypt
|
||||
- traefik.http.routers.pihole.service=pihole
|
||||
- traefik.http.services.pihole.loadbalancer.server.port=80
|
||||
- traefik.http.middlewares.set-forwarded-for.headers.hostsProxyHeaders=X-Forwarded-For
|
||||
- traefik.http.routers.pihole.middlewares=set-forwarded-for
|
||||
- traefik.docker.network=traefik
|
||||
placement:
|
||||
constraints:
|
||||
- node.role == manager
|
||||
|
|
|
@ -19,7 +19,7 @@ volumes:
|
|||
device: ":/mnt/data/seafile/db"
|
||||
|
||||
services:
|
||||
db:
|
||||
db:
|
||||
image: mariadb:10.5
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD={{ db_root_passwd }}
|
||||
|
@ -48,7 +48,7 @@ services:
|
|||
volume:
|
||||
nocopy: true
|
||||
environment:
|
||||
- DB_HOST=db
|
||||
- DB_HOST=db
|
||||
- DB_ROOT_PASSWD={{ db_root_passwd }}
|
||||
- TIME_ZONE=Europe/Amsterdam
|
||||
- SEAFILE_ADMIN_EMAIL={{ seafile_admin_email }}
|
||||
|
|
|
@ -6,7 +6,7 @@ networks:
|
|||
external: true
|
||||
|
||||
services:
|
||||
dashboard:
|
||||
swarm-dashboard:
|
||||
image: charypar/swarm-dashboard
|
||||
volumes:
|
||||
- type: bind
|
||||
|
|
|
@ -23,9 +23,18 @@ services:
|
|||
networks:
|
||||
- traefik
|
||||
ports:
|
||||
- 443:443
|
||||
- 80:80
|
||||
- 444:444
|
||||
- mode: host
|
||||
protocol: tcp
|
||||
published: 443
|
||||
target: 443
|
||||
- mode: host
|
||||
protocol: tcp
|
||||
published: 80
|
||||
target: 80
|
||||
- mode: host
|
||||
protocol: tcp
|
||||
published: 444
|
||||
target: 444
|
||||
deploy:
|
||||
placement:
|
||||
constraints:
|
||||
|
@ -116,3 +125,11 @@ services:
|
|||
- --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web
|
||||
|
||||
- --serversTransport.insecureSkipVerify=true
|
||||
|
||||
- --accesslog=true
|
||||
- --accesslog.fields.defaultmode=keep
|
||||
- --accesslog.fields.names.ClientUsername=drop
|
||||
- --accesslog.fields.headers.defaultmode=keep
|
||||
- --accesslog.fields.headers.names.User-Agent=keep
|
||||
- --accesslog.fields.headers.names.Authorization=drop
|
||||
- --accesslog.fields.headers.names.Content-Type=keep
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
pass=`secret-tool lookup ansible_vault shoarma`
|
||||
retval=$?
|
||||
|
||||
if [ $retval -ne 0 ]; then
|
||||
read -s pass
|
||||
fi
|
||||
echo $pass
|
61
flake.lock
Normal file
61
flake.lock
Normal file
|
@ -0,0 +1,61 @@
|
|||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1694529238,
|
||||
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1698266953,
|
||||
"narHash": "sha256-jf72t7pC8+8h8fUslUYbWTX5rKsRwOzRMX8jJsGqDXA=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "75a52265bda7fd25e06e3a67dee3f0354e73243c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
20
flake.nix
Normal file
20
flake.nix
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
description = "A basic flake with a shell";
|
||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||
inputs.flake-utils.url = "github:numtide/flake-utils";
|
||||
|
||||
outputs = { self, nixpkgs, flake-utils }:
|
||||
flake-utils.lib.eachDefaultSystem (system: let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
in {
|
||||
devShells.default = pkgs.mkShell {
|
||||
packages = with pkgs; [
|
||||
bashInteractive
|
||||
opentofu
|
||||
jq
|
||||
cdrtools
|
||||
ansible
|
||||
];
|
||||
};
|
||||
});
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
data "external" "secrets" {
|
||||
program = ["cat", pathexpand("~/.tfvars.json")]
|
||||
program = ["cat", pathexpand("~/.config/home/powerdns-api-key.json")]
|
||||
}
|
||||
|
||||
provider "powerdns" {
|
||||
|
@ -7,23 +7,6 @@ provider "powerdns" {
|
|||
api_key = data.external.secrets.result.powerdns_api_key
|
||||
}
|
||||
|
||||
resource "powerdns_record" "subdomain_pim" {
|
||||
for_each = toset(["dav", "git", "meet", "rss", "latex", "md", "swarm", "traefik", "syncthing", "cloud", "pihole", "ntfy", "apprise", "uptime", "concourse", "discourse"])
|
||||
zone = "pim.kunis.nl."
|
||||
name = "${each.key}.pim.kunis.nl."
|
||||
type = "CNAME"
|
||||
records = ["www.pim.kunis.nl."]
|
||||
ttl = 60
|
||||
}
|
||||
|
||||
resource "powerdns_record" "social_pim_kunis_nl_a" {
|
||||
zone = "pim.kunis.nl."
|
||||
name = "social.pim.kunis.nl."
|
||||
type = "A"
|
||||
records = ["84.245.14.149"]
|
||||
ttl = 60
|
||||
}
|
||||
|
||||
resource "powerdns_record" "kms_geokunis2_nl_a" {
|
||||
zone = "geokunis2.nl."
|
||||
name = "kms.geokunis2.nl."
|
||||
|
@ -71,3 +54,27 @@ resource "powerdns_record" "inbucket_geokunis2_nl_a" {
|
|||
records = ["84.245.14.149"]
|
||||
ttl = 60
|
||||
}
|
||||
|
||||
resource "powerdns_record" "smtp2go_1_geokunis2_nl_cname" {
|
||||
zone = "geokunis2.nl."
|
||||
name = "em670271.geokunis2.nl."
|
||||
type = "CNAME"
|
||||
records = ["return.smtp2go.net."]
|
||||
ttl = 60
|
||||
}
|
||||
|
||||
resource "powerdns_record" "smtp2go_2_geokunis2_nl_cname" {
|
||||
zone = "geokunis2.nl."
|
||||
name = "s670271._domainkey.geokunis2.nl."
|
||||
type = "CNAME"
|
||||
records = ["dkim.smtp2go.net."]
|
||||
ttl = 60
|
||||
}
|
||||
|
||||
resource "powerdns_record" "smtp2go_3_geokunis2_nl_cname" {
|
||||
zone = "geokunis2.nl."
|
||||
name = "link.geokunis2.nl."
|
||||
type = "CNAME"
|
||||
records = ["track.smtp2go.net."]
|
||||
ttl = 60
|
||||
}
|
||||
|
|
62
terraform/elasticsearch/main.tf
Normal file
62
terraform/elasticsearch/main.tf
Normal file
|
@ -0,0 +1,62 @@
|
|||
terraform {
|
||||
backend "pg" {
|
||||
schema_name = "shoarma-elasticsearch"
|
||||
}
|
||||
|
||||
required_providers {
|
||||
elasticstack = {
|
||||
source = "elastic/elasticstack"
|
||||
version = "0.6.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "elasticstack" {
|
||||
elasticsearch {
|
||||
endpoints = ["http://maestro.dmz:14653"]
|
||||
}
|
||||
}
|
||||
|
||||
resource "elasticstack_elasticsearch_index_lifecycle" "metrics_ilm" {
|
||||
name = "metrics_ilm"
|
||||
|
||||
delete {
|
||||
min_age = "7d"
|
||||
delete {}
|
||||
}
|
||||
}
|
||||
|
||||
resource "elasticstack_elasticsearch_index_template" "metrics_template" {
|
||||
name = "metrics_template"
|
||||
|
||||
priority = 42
|
||||
index_patterns = ["fluentd.cpu-*", "fluentd.memory-*", "fluentd.diskfree-*"]
|
||||
|
||||
template {
|
||||
settings = jsonencode({
|
||||
"index.lifecycle.name" = elasticstack_elasticsearch_index_lifecycle.metrics_ilm.name
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
resource "elasticstack_elasticsearch_index_lifecycle" "logs_ilm" {
|
||||
name = "logs_ilm"
|
||||
|
||||
delete {
|
||||
min_age = "2d"
|
||||
delete {}
|
||||
}
|
||||
}
|
||||
|
||||
resource "elasticstack_elasticsearch_index_template" "logs_template" {
|
||||
name = "logs_template"
|
||||
|
||||
priority = 42
|
||||
index_patterns = ["fluentd.access.**"]
|
||||
|
||||
template {
|
||||
settings = jsonencode({
|
||||
"index.lifecycle.name" = elasticstack_elasticsearch_index_lifecycle.logs_ilm.name
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
terraform {
|
||||
backend "pg" {
|
||||
schema_name = "shoarma"
|
||||
conn_str = "postgres://terraform@10.42.0.1/terraform_state"
|
||||
}
|
||||
|
||||
required_providers {
|
||||
libvirt = {
|
||||
source = "dmacvicar/libvirt"
|
||||
version = "0.7.1" # https://github.com/dmacvicar/terraform-provider-libvirt/issues/1040
|
||||
}
|
||||
|
||||
powerdns = {
|
||||
|
@ -17,66 +17,52 @@ terraform {
|
|||
}
|
||||
|
||||
provider "libvirt" {
|
||||
uri = "qemu+ssh://root@atlas.hyp/system"
|
||||
# https://libvirt.org/uri.html#libssh-and-libssh2-transport
|
||||
uri = "qemu+ssh://root@atlas.hyp/system?known_hosts=/etc/ssh/ssh_known_hosts"
|
||||
}
|
||||
|
||||
provider "libvirt" {
|
||||
alias = "jefke"
|
||||
uri = "qemu+ssh://root@jefke.hyp/system"
|
||||
uri = "qemu+ssh://root@jefke.hyp/system?known_hosts=/etc/ssh/ssh_known_hosts"
|
||||
}
|
||||
|
||||
module "manager" {
|
||||
source = "git::https://git.kun.is/home/tf-modules.git//debian"
|
||||
name = "maestro"
|
||||
domain_name = "tf-maestro"
|
||||
memory = 1024
|
||||
mac = "CA:FE:C0:FF:EE:08"
|
||||
hypervisor_host = "atlas.hyp"
|
||||
provider "libvirt" {
|
||||
alias = "lewis"
|
||||
uri = "qemu+ssh://root@lewis.hyp/system?known_hosts=/etc/ssh/ssh_known_hosts"
|
||||
}
|
||||
|
||||
module "maestro" {
|
||||
source = "git::https://git.kun.is/home/tf-modules.git//debian"
|
||||
name = "maestro"
|
||||
domain_name = "tf-maestro"
|
||||
memory = 10240
|
||||
mac = "CA:FE:C0:FF:EE:08"
|
||||
providers = {
|
||||
libvirt = libvirt
|
||||
}
|
||||
}
|
||||
|
||||
module "swarmpub1" {
|
||||
source = "git::https://git.kun.is/home/tf-modules.git//debian"
|
||||
name = "swarmpub1"
|
||||
domain_name = "tf-swarmpub1"
|
||||
memory = 1024 * 5
|
||||
hypervisor_host = "atlas.hyp"
|
||||
providers = {
|
||||
libvirt = libvirt
|
||||
}
|
||||
}
|
||||
module "bancomart" {
|
||||
source = "git::https://git.kun.is/home/tf-modules.git//debian"
|
||||
name = "bancomart"
|
||||
domain_name = "tf-bancomart"
|
||||
memory = 10240
|
||||
disk_pool = "disks"
|
||||
cloudinit_pool = "cloudinit"
|
||||
disk_base_pool = "images"
|
||||
bridge_name = "bridgedmz"
|
||||
|
||||
module "swarmpriv1" {
|
||||
source = "git::https://git.kun.is/home/tf-modules.git//debian"
|
||||
name = "swarmpriv1"
|
||||
domain_name = "tf-swarmpriv1"
|
||||
memory = 1024 * 5
|
||||
hypervisor_host = "atlas.hyp"
|
||||
providers = {
|
||||
libvirt = libvirt
|
||||
}
|
||||
}
|
||||
|
||||
module "swarmpub2" {
|
||||
source = "git::https://git.kun.is/home/tf-modules.git//debian"
|
||||
name = "swarmpub2"
|
||||
domain_name = "tf-swarmpub2"
|
||||
memory = 1024 * 3
|
||||
hypervisor_host = "jefke.hyp"
|
||||
providers = {
|
||||
libvirt = libvirt.jefke
|
||||
}
|
||||
}
|
||||
|
||||
module "swarmpriv2" {
|
||||
source = "git::https://git.kun.is/home/tf-modules.git//debian"
|
||||
name = "swarmpriv2"
|
||||
domain_name = "tf-swarmpriv2"
|
||||
memory = 1024 * 3
|
||||
hypervisor_host = "jefke.hyp"
|
||||
module "vpay" {
|
||||
source = "git::https://git.kun.is/home/tf-modules.git//debian"
|
||||
name = "vpay"
|
||||
domain_name = "tf-vpay"
|
||||
memory = 3 * 1024
|
||||
providers = {
|
||||
libvirt = libvirt.jefke
|
||||
libvirt = libvirt.lewis
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue