Compare commits

...

17 Commits

Author SHA1 Message Date
bee 6873ef44e4 ott and stuff 2026-06-18 12:25:18 +02:00
bee fa1231d1f8 backup and stuff 2026-06-12 15:14:27 +02:00
bee c0ae209a9d gitea migration 2026-05-31 15:19:59 +02:00
bee 11b13cd326 fixes/security 2026-05-31 09:35:54 +02:00
bee 85cf6f5533 fail2forward 2026-05-31 00:10:02 +02:00
bee fdc99031dd immich 2026-05-30 23:17:43 +02:00
bee 34d8d82dbf ingress 2026-05-26 17:21:03 +02:00
bee af81ce3df8 outsourcing 2026-05-25 23:21:51 +02:00
bee 808ff14aba stuff 2026-05-25 22:06:31 +02:00
bee 9729b28681 mail done 2026-05-25 11:09:11 +02:00
bee 366a8cc197 mail 2026-05-24 19:38:38 +02:00
bee 8c66580dab matrix 2026-05-23 17:48:04 +02:00
bee 3273885e11 updates 2026-05-02 13:59:46 +02:00
bee d56ff74f96 fail2ban 2026-04-28 15:47:50 +02:00
bee 5558ed473a logging stack and firewall 2026-04-28 11:00:23 +02:00
bee 645c0389fb fixed forwarding 2026-04-27 17:31:03 +02:00
bee 4058d2b108 added ufw 2026-04-27 17:22:33 +02:00
84 changed files with 2918 additions and 133 deletions
+4
View File
@@ -2,3 +2,7 @@ registry/
.ansible/ .ansible/
.vscode/settings.json .vscode/settings.json
.vault-password .vault-password
*.private
*.secret
mail.txt
containers/opentogethertube
+135 -2
View File
@@ -51,15 +51,148 @@
} }
}, },
{ {
"label": "Build & Push: postfix", "label": "Deploy: ufw",
"type": "shell", "type": "shell",
"command": "make push-postfix", "command": "make deploy-ufw",
"group": "build", "group": "build",
"presentation": { "presentation": {
"reveal": "always", "reveal": "always",
"panel": "dedicated" "panel": "dedicated"
} }
},
{
"label": "Deploy: fail2ban",
"type": "shell",
"command": "make deploy-fail2ban",
"group": "build",
"presentation": {
"reveal": "always",
"panel": "dedicated"
} }
},
{
"label": "Deploy: fail2ban-ingress",
"type": "shell",
"command": "make deploy-fail2ban-ingress",
"group": "build",
"presentation": {
"reveal": "always",
"panel": "dedicated"
}
},
{
"label": "Deploy: mail",
"type": "shell",
"command": "make deploy-mail",
"group": "build",
"presentation": {
"reveal": "always",
"panel": "dedicated"
}
},
{
"label": "Deploy: backup",
"type": "shell",
"command": "make deploy-backup",
"group": "build",
"presentation": {
"reveal": "always",
"panel": "dedicated"
}
},
{
"label": "Deploy: wireguard",
"type": "shell",
"command": "make deploy-wireguard",
"group": "build",
"presentation": {
"reveal": "always",
"panel": "dedicated"
}
},
{
"label": "Deploy: ufw-ingress",
"type": "shell",
"command": "make deploy-ufw-ingress",
"group": "build",
"presentation": {
"reveal": "always",
"panel": "dedicated"
}
},
{
"label": "Deploy: wireguard-ingress",
"type": "shell",
"command": "make deploy-wireguard-ingress",
"group": "build",
"presentation": {
"reveal": "always",
"panel": "dedicated"
}
},
{
"label": "Deploy: matrix",
"type": "shell",
"command": "make deploy-matrix",
"group": "build",
"presentation": {
"reveal": "always",
"panel": "dedicated"
}
},
{
"label": "Deploy: openvpn",
"type": "shell",
"command": "make deploy-openvpn",
"group": "build",
"presentation": {
"reveal": "always",
"panel": "dedicated"
}
},
{
"label": "Deploy: immich",
"type": "shell",
"command": "make deploy-immich",
"group": "build",
"presentation": {
"reveal": "always",
"panel": "dedicated"
}
},
{
"label": "Deploy: ott",
"type": "shell",
"command": "make deploy-ott",
"group": "build",
"presentation": {
"reveal": "always",
"panel": "dedicated"
}
},
{
"label": "Build & Push: ott",
"type": "shell",
"command": "make push-ott",
"group": "build",
"presentation": {
"reveal": "always",
"panel": "dedicated"
},
"options": {
"cwd": "${workspaceFolder}/containers/ott"
}
}
// {
// "label": "Build & Push: <template>",
// "type": "shell",
// "command": "make push-<template>",
// "group": "build",
// "presentation": {
// "reveal": "always",
// "panel": "dedicated"
// }
// }
], ],
"inputs": [ "inputs": [
{ {
@@ -1,5 +1,5 @@
- name: Nginx - name: Nginx
hosts: pi hosts: beepi
become: true become: true
vars: vars:
uplink_password: !vault | uplink_password: !vault |
+46
View File
@@ -0,0 +1,46 @@
- name: Gitea
hosts: beepi
become: true
vars:
gitea_db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
63336533393735346165633965383866393736336365646330346236356239363737353234383637
6261383166323062663033346136633066303462343263320a333932646162336232373530373834
65386637336562646135613563356137313239336365653161386434313835633437613233343332
3736353865313938300a383266353538666135353866653263663133663232646430323966353134
3939
tasks:
- name: Install podman
ansible.builtin.apt:
name: podman
state: present
- name: Install podman-compose
ansible.builtin.apt:
name: podman-compose
state: present
- name: Create gitea directory
ansible.builtin.file:
path: /opt/beeserver/gitea
state: directory
mode: '0755'
- name: Compose down
changed_when: true
failed_when: false
ansible.builtin.command:
cmd: podman-compose down
chdir: /opt/beeserver/gitea
- name: Copy compose
ansible.builtin.template:
src: docker-compose.yml.j2
dest: /opt/beeserver/gitea/docker-compose.yml
mode: '0644'
- name: Compose up
changed_when: true
ansible.builtin.command:
cmd: podman-compose up -d
chdir: /opt/beeserver/gitea
@@ -1,5 +1,5 @@
- name: Inspircd - name: Inspircd
hosts: pi hosts: beepi
become: true become: true
vars: vars:
inspircd_sendpass: !vault | inspircd_sendpass: !vault |
+5
View File
@@ -0,0 +1,5 @@
FROM debian:bookworm-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends opendkim \
&& rm -rf /var/lib/apt/lists/*
CMD ["opendkim", "-f"]
@@ -6,8 +6,6 @@ RUN apt-get update \
libsasl2-modules \ libsasl2-modules \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
COPY main.cf /etc/postfix/main.cf
EXPOSE 25 587 EXPOSE 25 587
CMD ["postfix", "start-fg"] CMD ["postfix", "start-fg"]
@@ -1,5 +1,5 @@
- name: Thelounge - name: Thelounge
hosts: pi hosts: beepi
become: true become: true
tasks: tasks:
- name: Install nodejs - name: Install nodejs
+7
View File
@@ -0,0 +1,7 @@
REGISTRY := git.secretbee.buzz
build-ott:
cd opentogethertube && podman build --platform linux/arm64 -t $(REGISTRY)/bee/ott:latest --target docker-stage -f deploy/monolith.Dockerfile .
push-ott: build-ott
podman push $(REGISTRY)/bee/ott:latest
+3
View File
@@ -3,3 +3,6 @@ pi:
beepi: beepi:
ansible_host: beepi.local ansible_host: beepi.local
ansible_python_interpreter: auto_silent ansible_python_interpreter: auto_silent
animeistrash:
ansible_host: animeistrash.org
ansible_python_interpreter: auto_silent
+1 -1
View File
@@ -2,7 +2,7 @@ REGISTRY := git.secretbee.buzz
INVENTORY := inventory.yml INVENTORY := inventory.yml
build-%: build-%:
podman build --platform linux/arm64 -t $(REGISTRY)/bee/$*:latest playbooks/$* podman build --platform linux/arm64 -t $(REGISTRY)/bee/$*:latest containers/$*
push-%: build-% push-%: build-%
podman push $(REGISTRY)/bee/$*:latest podman push $(REGISTRY)/bee/$*:latest
+21
View File
@@ -0,0 +1,21 @@
- name: Autodns
hosts: beepi
become: true
vars:
njalla_api_token: !vault |
$ANSIBLE_VAULT;1.1;AES256
65666463616462633533663835383164353566326437333336616266333864333465613732346633
6534633837373937393563633966343738316562653930610a346461613236653266303237306663
66663234313832373939346539386633316465373861663862646537303662313564363038303164
3865666132613130380a623737663837343438333837626338346565653735613435313164373663
33316231366334623461303263386136656234613133373361353262346366636133396134663838
3733353465643235653337306434396366623935303862633737
$ANSIBLE_VAULT;1.1;AES256
65666463616462633533663835383164353566326437333336616266333864333465613732346633
6534633837373937393563633966343738316562653930610a346461613236653266303237306663
66663234313832373939346539386633316465373861663862646537303662313564363038303164
3865666132613130380a623737663837343438333837626338346565653735613435313164373663
33316231366334623461303263386136656234613133373361353262346366636133396134663838
3733353465643235653337306434396366623935303862633737
tasks:
+63
View File
@@ -0,0 +1,63 @@
- name: Backup
hosts: beepi
become: true
vars:
gpg_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
34383033383462626132353163303532376137613539326662383038663537633465373863396539
6139623961303165353230303637303530343136363165380a323534663665323836636165323237
39653863313962353033336338376462303962323762663139663136663033306161316361303630
6466663761643438360a653166616130633862643236633663303731356337326361636436646439
37303633353961623766313063363734376334383163376337376639306135373064
tasks:
- name: Install rsync
ansible.builtin.apt:
name: rsync
state: present
- name: Create backup directory
ansible.builtin.file:
path: /opt/backup
state: directory
mode: '0700'
- name: Copy daily
ansible.builtin.copy:
src: backupDaily.sh
dest: /opt/backup/backupDaily.sh
mode: '0700'
- name: Copy weekly
ansible.builtin.copy:
src: backupWeekly.sh
dest: /opt/backup/backupWeekly.sh
mode: '0700'
- name: Copy passphrase
ansible.builtin.template:
src: passphrase.txt.j2
dest: /opt/backup/passphrase.txt
mode: '0600'
- name: Set path
ansible.builtin.cron:
name: PATH
env: true
job: /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
- name: Schedule daily backup
ansible.builtin.cron:
name: beepi backup daily
user: root
minute: '0'
hour: '3'
job: /opt/backup/backupDaily.sh >> /var/log/beepi-backup.log 2>&1
- name: Schedule weekly backup
ansible.builtin.cron:
name: beepi backup weekly
user: root
minute: '0'
hour: '5'
weekday: '0'
job: /opt/backup/backupWeekly.sh >> /var/log/beepi-backup.log 2>&1
+72
View File
@@ -0,0 +1,72 @@
#!/bin/bash
set -euo pipefail
now=$(date +"%Y%m%d%H%M")
declare -a arr=("mail" "matrix" "monitoring")
declare -a monitoring=("monitoring_prometheus-data" "monitoring_grafana-storage" "monitoring_loki-data" "monitoring_alloy-data")
declare -a matrix=("matrix_db")
declare -a immich=("systemd-immich-pgdata" "systemd-immich-upload")
gitea_uid=$(id -u gitea)
immich_uid=$(id -u immich)
restore() {
for i in "${arr[@]}"; do
cd /opt/beeserver/${i}
podman-compose up -d
done
for j in "${monitoring[@]}"; do
rm -rf /opt/beeserver/monitoring/${j}.tar
done
for j in "${matrix[@]}"; do
rm -rf /opt/beeserver/matrix/${j}.tar
done
systemctl --user --machine gitea@.host start gitea-db.service gitea-server.service || true
systemctl --user --machine immich@.host start immich-db.service immich-redis.service immich-server.service || true
rm -f /home/immich/systemd-immich-*.tar
}
trap restore EXIT
for i in "${arr[@]}"
do
cd /opt/beeserver/${i}
podman-compose down -t 60
if [[ "$i" == "monitoring" ]]
then
for j in "${monitoring[@]}"
do
podman volume export ${j} --output ${j}.tar
done
fi
if [[ "$i" == "matrix" ]]
then
for j in "${matrix[@]}"
do
podman volume export ${j} --output ${j}.tar
done
fi
rsync -aH /opt/beeserver/${i} /opt/backup/beeserver
podman-compose up -d
done
systemctl --user --machine gitea@.host stop gitea-server.service gitea-db.service
rsync -aH /home/gitea/data /opt/backup/beeserver/gitea
systemctl --user --machine gitea@.host start gitea-db.service gitea-server.service
systemctl --user --machine immich@.host stop immich-server.service immich-db.service immich-redis.service
for v in "${immich[@]}"
do
sudo -u immich XDG_RUNTIME_DIR=/run/user/${immich_uid} podman volume export ${v} --output /home/immich/${v}.tar
done
systemctl --user --machine immich@.host start immich-db.service immich-redis.service immich-server.service
mkdir -p /opt/backup/beeserver/immich/
mv /home/immich/systemd-immich-*.tar /opt/backup/beeserver/immich/
tar -czf - /opt/backup/beeserver | gpg --batch --passphrase-file /opt/backup/passphrase.txt -c -o /home/beeshare/raid/serverBackup/beeserver_daily_${now}.tar.gz.gpg
+15
View File
@@ -0,0 +1,15 @@
#!/bin/bash
set -euo pipefail
now=$(date +"%Y%m%d%H%M")
tar -czf - /opt/backup/beeserver | gpg --batch --passphrase-file /opt/backup/passphrase.txt -c -o /home/beeshare/raid/serverBackup/beeserver_weekly_${now}.tar.gz.gpg
if [ -s /home/beeshare/raid/serverBackup/beeserver_weekly_${now}.tar.gz.gpg ]
then
rm -rf /opt/backup/beeserver
fi
find /home/beeshare/raid/serverBackup -maxdepth 1 -name 'beeserver_weekly_*.tar.gz.gpg' -mtime +30 -delete
find /home/beeshare/raid/serverBackup -maxdepth 1 -name 'beeserver_daily_*.tar.gz.gpg' -mtime +7 -delete
+1
View File
@@ -0,0 +1 @@
{{ gpg_password }}
@@ -0,0 +1,52 @@
- name: Fail2ban-ingress
hosts: animeistrash
become: true
tasks:
- name: Install fail2ban
ansible.builtin.apt:
name: fail2ban
state: present
- name: Create user
ansible.builtin.user:
name: fail2forward
create_home: true
- name: Create .ssh
ansible.builtin.file:
name: /home/fail2forward/.ssh
owner: fail2forward
group: fail2forward
state: directory
mode: '0700'
- name: Create authorized_keys
ansible.builtin.copy:
content: "command=\"/usr/local/bin/fail2forward\",no-pty,no-agent-forwarding,no-X11-forwarding,no-port-forwarding,restrict \
{{ lookup('ansible.builtin.file', '../fail2ban/fail2forward_id_rsa.pub') }}"
owner: fail2forward
group: fail2forward
dest: /home/fail2forward/.ssh/authorized_keys
mode: '0644'
- name: Copy fail2forward script
ansible.builtin.template:
src: fail2forward.j2
dest: /usr/local/bin/fail2forward
owner: root
group: root
mode: '0755'
- name: Copy jail.local
ansible.builtin.template:
src: jail.local.j2
dest: /etc/fail2ban/jail.local
owner: root
group: root
mode: '0644'
- name: Restart fail2ban
ansible.builtin.service:
name: fail2ban
state: restarted
@@ -0,0 +1,17 @@
#!/bin/bash
set -euo pipefail
case "$SSH_ORIGINAL_COMMAND" in
"ban "*)
ip="${SSH_ORIGINAL_COMMAND#ban }"
[[ "$ip" =~ ^[0-9.]+$|^[0-9a-fA-F:]+$ ]] || { echo "bad ip"; exit 1; }
exec fail2ban-client set sshd banip "$ip"
;;
"unban "*)
ip="${SSH_ORIGINAL_COMMAND#unban }"
[[ "$ip" =~ ^[0-9.]+$|^[0-9a-fA-F:]+$ ]] || { echo "bad ip"; exit 1; }
exec fail2ban-client set sshd unbanip "$ip"
;;
*)
echo "denied" >&2; exit 1
;;
esac
+12
View File
@@ -0,0 +1,12 @@
[DEFAULT]
bantime = 24h
findtime = 10m
maxretry = 5
banaction = ufw
bantime.increment = true
bantime.multipliers = 1 5 30 60 300 720 1440 2880
[sshd]
enabled = true
port = ssh
backend = systemd
+52
View File
@@ -0,0 +1,52 @@
- name: Fail2ban
hosts: beepi
become: true
tasks:
- name: Install fail2ban
ansible.builtin.apt:
name: fail2ban
state: present
- name: Create user
ansible.builtin.user:
name: fail2forward
create_home: true
- name: Create key
ansible.builtin.user:
name: fail2forward
generate_ssh_key: true
ssh_key_bits: 2048
ssh_key_type: ed25519
ssh_key_file: .ssh/id_rsa
register: ssh_public_key
- name: Save public key locally
ansible.builtin.copy:
content: "{{ ssh_public_key.ssh_public_key }}"
dest: ./fail2forward_id_rsa.pub
mode: '0644'
delegate_to: localhost
become: false
- name: Copy jail.local
ansible.builtin.template:
src: jail.local.j2
dest: /etc/fail2ban/jail.local
owner: root
group: root
mode: '0644'
- name: Copy forward.conf
ansible.builtin.template:
src: forward.conf.j2
dest: /etc/fail2ban/action.d/forward.conf
owner: root
group: root
mode: '0644'
- name: Restart fail2ban
ansible.builtin.service:
name: fail2ban
state: restarted
@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCpbmyeKy5UjpTrLJk/QYzagg4MHfBV0/wPsAicn9jzxiK3Pqtn4zTCLchBis5Cfoc1aQCqUSp3X6CCjO5FIU0uaMAQPrZneecpSyDbNGkJuUM7JE2dY2pvMSdPpwzR54aauW56/HhtTARVZwgFOKwjcBaf3Fv98qiAzTTqGJjSJOZ6nFiuPm0PQ40867bUFLHuIJJBJVg3PHy+k0mUIsA8yF3ksSQOgyms2Iy54G6hL8ynpDoiLilbc4iYpBAyKjFCHx3Si1LIIH/hp2znexuzLRK68G7a919sEw+OT1h2gJLBnA6G36UwR4rVIQkNdScuM2WzggqGIdgbK8lOSCXf ansible-generated on beepi
+12
View File
@@ -0,0 +1,12 @@
[Definition]
actionstart =
actionstop =
actioncheck =
actionban = sudo -u fail2forward ssh -i ~fail2forward/.ssh/id_rsa -o BatchMode=yes -o ConnectTimeout=5 -o ServerAliveInterval=5 <forward_user>@<forward_host> ban <ip>
actionunban = sudo -u fail2forward ssh -i ~fail2forward/.ssh/id_rsa -o BatchMode=yes -o ConnectTimeout=5 -o ServerAliveInterval=5 <forward_user>@<forward_host> unban <ip>
[Init]
forward_host = animeistrash.org
forward_user = fail2forward
+31
View File
@@ -0,0 +1,31 @@
[DEFAULT]
bantime = 24h
findtime = 10m
maxretry = 5
banaction = ufw
bantime.increment = true
bantime.multipliers = 1 5 30 60 300 720 1440 2880
ignoreip = 81.217.198.106 # home ip
action = %(action_)s
forward
[sshd]
enabled = true
port = ssh,2222,4444
[nginx-http-auth]
enabled = true
[nginx-limit-req]
enabled = true
[postfix]
enabled = true
port = smtp,submission
logpath = /opt/beeserver/mail/mail-logs/mail.log
[dovecot]
enabled = true
port = imaps,pop3s
logpath = /opt/beeserver/mail/mail-logs/mail.log
+17
View File
@@ -0,0 +1,17 @@
[Unit]
Description=Gitea Postgres
[Container]
ContainerName=gitea-db
Image=docker.io/library/postgres:14
Network=gitea.network
Volume=/home/gitea/data/postgres:/var/lib/postgresql/data
Environment=POSTGRES_USER=gitea
Environment=POSTGRES_PASSWORD={{ gitea_db_password }}
Environment=POSTGRES_DB=gitea
[Service]
Restart=on-failure
[Install]
WantedBy=default.target
+30
View File
@@ -0,0 +1,30 @@
[Unit]
Description=Gitea Server
Requires=gitea-db.service
After=gitea-db.service
[Container]
ContainerName=gitea-server
Image=docker.gitea.com/gitea:1.26.0
Network=gitea.network
PublishPort=3000:3000
PublishPort=2222:2222
Volume=/home/gitea/data/gitea:/data
Volume=/etc/timezone:/etc/timezone:ro
Volume=/etc/localtime:/etc/localtime:ro
Environment=USER_UID=1000
Environment=USER_GID=1000
Environment=GITEA__database__DB_TYPE=postgres
Environment=GITEA__database__HOST=gitea-db:5432
Environment=GITEA__database__NAME=gitea
Environment=GITEA__database__USER=gitea
Environment=GITEA__database__PASSWD={{ gitea_db_password }}
Environment=GITEA__server__SSH_LISTEN_PORT=2222
Environment=GITEA__server__SSH_PORT=2222
Environment=SSH_LISTEN_PORT=2222
[Service]
Restart=on-failure
[Install]
WantedBy=default.target
+89 -24
View File
@@ -1,7 +1,9 @@
- name: Inspircd - name: Gitea
hosts: pi hosts: beepi
become: true become: true
vars: vars:
user: gitea
user_home: /home/gitea
gitea_db_password: !vault | gitea_db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256 $ANSIBLE_VAULT;1.1;AES256
63336533393735346165633965383866393736336365646330346236356239363737353234383637 63336533393735346165633965383866393736336365646330346236356239363737353234383637
@@ -10,36 +12,99 @@
3736353865313938300a383266353538666135353866653263663133663232646430323966353134 3736353865313938300a383266353538666135353866653263663133663232646430323966353134
3939 3939
tasks: tasks:
- name: Install podman - name: Install dependencies
ansible.builtin.apt: ansible.builtin.apt:
name: podman name: "{{ item }}"
state: present state: present
loop:
- podman
- systemd-container
- passt
- name: Install podman-compose - name: Create user
ansible.builtin.apt: ansible.builtin.user:
name: podman-compose name: "{{ user }}"
state: present home: "{{ user_home }}"
shell: /usr/sbin/nologin
create_home: true
register: user_info
- name: Create gitea directory - name: Enable linger
ansible.builtin.command:
cmd: "loginctl enable-linger {{ user }}"
creates: "/var/lib/systemd/linger/{{ user }}"
- name: Create quadlet directory
ansible.builtin.file: ansible.builtin.file:
path: /opt/gitea path: "{{ user_home }}/.config/containers/systemd"
state: directory state: directory
owner: "{{ user }}"
group: "{{ user }}"
mode: '0755' mode: '0755'
- name: Copy compose - name: Create data directory
ansible.builtin.template: ansible.builtin.file:
src: docker-compose.yml.j2 path: "{{ user_home }}/data"
dest: /opt/gitea/docker-compose.yml state: directory
owner: "{{ user }}"
group: "{{ user }}"
mode: '0755'
- name: Copy network
ansible.builtin.copy:
dest: "{{ user_home }}/.config/containers/systemd/gitea.network"
content: "[Network]\n"
owner: "{{ user }}"
group: "{{ user }}"
mode: '0644' mode: '0644'
- name: Compose down - name: Deploy db quadlet
changed_when: true ansible.builtin.template:
ansible.builtin.command: src: gitea-db.container.j2
cmd: podman-compose down dest: "{{ user_home }}/.config/containers/systemd/gitea-db.container"
chdir: /opt/gitea owner: "{{ user }}"
group: "{{ user }}"
mode: '0600'
- name: Compose up - name: Deploy server quadlet
changed_when: true ansible.builtin.template:
ansible.builtin.command: src: gitea-server.container.j2
cmd: podman-compose up -d dest: "{{ user_home }}/.config/containers/systemd/gitea-server.container"
chdir: /opt/gitea owner: "{{ user }}"
group: "{{ user }}"
mode: '0600'
- name: Reload user systemd
become: true
become_user: "{{ user }}"
environment:
XDG_RUNTIME_DIR: "/run/user/{{ user_info.uid }}"
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ user_info.uid }}/bus"
ansible.builtin.systemd:
daemon_reload: true
scope: user
- name: Start user manager
ansible.builtin.systemd:
name: "user@{{ user_info.uid }}.service"
state: started
- name: Start gitea-server
become: true
become_user: "{{ user }}"
environment:
XDG_RUNTIME_DIR: "/run/user/{{ user_info.uid }}"
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ user_info.uid }}/bus"
ansible.builtin.systemd:
name: gitea-server.service
state: started
scope: user
- name: Debug
ansible.builtin.debug:
msg:
- "Service status: systemctl --user --machine {{ user_info.name }}@.host status gitea-server"
- "Read logs: sudo journalctl _UID={{ user_info.uid }} -n 200 --no-pager"
- "Shell: machinectl shell {{ user_info.name }}@.host /bin/bash"
tags:
- always
+17
View File
@@ -0,0 +1,17 @@
[Unit]
Description=Immich Postgres
[Container]
ContainerName=immich-db
Image=ghcr.io/immich-app/postgres:14-vectorchord0.4.3
Network=immich.network
Volume=immich-pgdata.volume:/var/lib/postgresql/data
Environment=POSTGRES_USER=immich
Environment=POSTGRES_PASSWORD={{ immich_db_password }}
Environment=POSTGRES_DB=immich
[Service]
Restart=on-failure
[Install]
WantedBy=default.target
+13
View File
@@ -0,0 +1,13 @@
[Unit]
Description=Immich Redis
[Container]
ContainerName=immich-redis
Image=docker.io/redis:6.2-alpine
Network=immich.network
[Service]
Restart=on-failure
[Install]
WantedBy=default.target
@@ -0,0 +1,23 @@
[Unit]
Description=Immich Server
Requires=immich-db.service immich-redis.service
After=immich-db.service immich-redis.service
[Container]
ContainerName=immich-server
Image=ghcr.io/immich-app/immich-server:release
Network=immich.network
PublishPort=127.0.0.1:2283:2283
Volume=immich-upload.volume:/usr/src/app/upload
Environment=DB_HOSTNAME=immich-db
Environment=DB_USERNAME=immich
Environment=DB_PASSWORD={{ immich_db_password }}
Environment=DB_DATABASE_NAME=immich
Environment=REDIS_HOSTNAME=immich-redis
Environment=IMMICH_MACHINE_LEARNING_ENABLED=false
[Service]
Restart=on-failure
[Install]
WantedBy=default.target
+118
View File
@@ -0,0 +1,118 @@
- name: Immich
hosts: beepi
become: true
vars:
immich_db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
64666332336435616365303563636634373333346537643336626235316432643336303665646463
3735653065653561643635376237393666313137303661370a336664623937623061313663303835
37623866383831623433366132346232663862653566653139323630356466653134363035363836
3061376330316365310a393961343065633937336534306265663733653665383233383030326439
30633861353033656264663439623264383536376664613665613138623262623261
tasks:
- name: Install dependencies
ansible.builtin.apt:
name: "{{ item }}"
state: present
loop:
- podman
- systemd-container
- passt
- name: Create immich user
ansible.builtin.user:
name: immich
home: /home/immich
shell: /usr/sbin/nologin
create_home: true
register: immich_user_info
- name: Enable linger
ansible.builtin.command:
cmd: "loginctl enable-linger immich"
creates: "/var/lib/systemd/linger/immich"
- name: Create quadlet directory
ansible.builtin.file:
path: "/home/immich/.config/containers/systemd"
state: directory
owner: "immich"
group: "immich"
mode: '0755'
- name: Copy network
ansible.builtin.copy:
dest: "/home/immich/.config/containers/systemd/immich.network"
content: "[Network]\n"
owner: immich
group: immich
mode: '0644'
- name: Copy volumes
ansible.builtin.copy:
dest: "/home/immich/.config/containers/systemd/{{ item }}.volume"
content: "[Volume]\n"
owner: immich
group: immich
mode: '0644'
loop:
- immich-pgdata
- immich-upload
- name: Deploy db quadlet
ansible.builtin.template:
src: immich-db.container.j2
dest: "/home/immich/.config/containers/systemd/immich-db.container"
owner: immich
group: immich
mode: '0600'
- name: Deploy redis quadlet
ansible.builtin.copy:
src: immich-redis.container
dest: "/home/immich/.config/containers/systemd/immich-redis.container"
owner: immich
group: immich
mode: '0644'
- name: Deploy server quadlet
ansible.builtin.template:
src: immich-server.container.j2
dest: "/home/immich/.config/containers/systemd/immich-server.container"
owner: immich
group: immich
mode: '0600'
- name: Reload user systemd
become: true
become_user: immich
environment:
XDG_RUNTIME_DIR: "/run/user/{{ immich_user_info.uid }}"
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ immich_user_info.uid }}/bus"
ansible.builtin.systemd:
daemon_reload: true
scope: user
- name: Start user manager for immich
ansible.builtin.systemd:
name: "user@{{ immich_user_info.uid }}.service"
state: started
- name: Start immich-server
become: true
become_user: immich
environment:
XDG_RUNTIME_DIR: "/run/user/{{ immich_user_info.uid }}"
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ immich_user_info.uid }}/bus"
ansible.builtin.systemd:
name: immich-server.service
state: started
scope: user
- name: Debug
ansible.builtin.debug:
msg:
- "Service status: systemctl --user --machine {{ immich_user_info.name }}@.host status immich-server"
- "Read logs: sudo journalctl _UID={{ immich_user_info.uid }} -n 200 --no-pager"
- "Shell: machinectl shell {{ immich_user_info.name }}@.host /bin/bash"
+10 -30
View File
@@ -1,5 +1,5 @@
- name: Letsencrypt - name: Letsencrypt
hosts: pi hosts: beepi
become: true become: true
tasks: tasks:
- name: Install Certbot - name: Install Certbot
@@ -9,35 +9,15 @@
- name: Request root certificates - name: Request root certificates
changed_when: true changed_when: true
ansible.builtin.command: certbot certonly --nginx -m secretbumblebee@proton.me --agree-tos -n --domains secretbee.buzz ansible.builtin.command: "certbot certonly --nginx -m secretbumblebee@proton.me --agree-tos -n --domains {{ item }}"
loop:
- name: Request root certificates - secretbee.buzz
changed_when: true - git.secretbee.buzz
ansible.builtin.command: certbot certonly --nginx -m secretbumblebee@proton.me --agree-tos -n --domains lounge.secretbee.buzz - grafana.secretbee.buzz
- mail.secretbee.buzz
- name: Request irc certificates - matrix.secretbee.buzz
changed_when: true - gallery.secretbee.buzz
ansible.builtin.command: certbot certonly --nginx -m secretbumblebee@proton.me --agree-tos -n --domains irc.secretbee.buzz - ott.secretbee.buzz
- name: Request git certificates
changed_when: true
ansible.builtin.command: certbot certonly --nginx -m secretbumblebee@proton.me --agree-tos -n --domains git.secretbee.buzz
- name: Request grafana certificates
changed_when: true
ansible.builtin.command: certbot certonly --nginx -m secretbumblebee@proton.me --agree-tos -n --domains grafana.secretbee.buzz
- name: Add post hook script
ansible.builtin.copy:
src: irc-post-hook.sh
dest: /opt/irc-post-hook.sh
owner: root
group: root
mode: '0755'
- name: Renew for post hook
changed_when: true
ansible.builtin.command: certbot renew --cert-name irc.secretbee.buzz --deploy-hook /opt/irc-post-hook.sh --force-renewal
- name: Change permission on live - name: Change permission on live
ansible.builtin.file: ansible.builtin.file:
+20
View File
@@ -0,0 +1,20 @@
services: # https://docker-mailserver.github.io/docker-mailserver/latest/
mailserver:
image: ghcr.io/docker-mailserver/docker-mailserver:15.1.0
container_name: mailserver
hostname: mail.secretbee.buzz
env_file: mailserver.env
ports:
- "25:25"
- "465:465"
- "587:587"
- "993:993"
volumes:
- /opt/beeserver/mail/mail-data/:/var/mail/
- /opt/beeserver/mail/mail-state/:/var/mail-state/
- /opt/beeserver/mail/mail-logs/:/var/log/mail/
- /opt/beeserver/mail/config/:/tmp/docker-mailserver/
- /etc/localtime:/etc/localtime:ro
- /etc/letsencrypt:/etc/letsencrypt:ro
restart: always
stop_grace_period: 1m
+83
View File
@@ -0,0 +1,83 @@
- name: Mail
hosts: beepi
become: true
vars:
relay_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
62623366656634653035626534353134343961313434373635393163623134393132336465383838
3635646434353935396136346135373238623433666563340a626463653537326331303233363734
65633237386135313266366533386465396662663561396265343731666337363062663263323537
3165616638653634310a666238656466306433346235396537386539366436333032373866333731
64323037613336613538613866343738613236323739333339313133386263323037313837636131
6533666231663438336566386130366536623565383837623164
relay_user: !vault |
$ANSIBLE_VAULT;1.1;AES256
66636637636636363133366335653835343130616134356330386531653537346138326432336662
3231636236393635646465626538643736326432633866620a633166346632613132323530373631
38333935373565616633363530616533656536313461363935623966336265613264373439613461
3133383935656337370a653461363636616537343836383935356432303532363861383863363639
31316537333565623530333332353435353437313466353935636139653762643930
relay_password_smtp2go: !vault |
$ANSIBLE_VAULT;1.1;AES256
30353034303936383336616430373037316663333039326337633838336532326462643039323930
3865396234396464363032346335663961323462643232310a363163353231303763323032646637
61346265343333303735623635633638393265336530656539623063346338646636643661333962
3961643332623365660a336130313864326463623365333435383533623837623831326234323466
39303363393736616230343331623734636364313039356137643864383833616664
relay_user_smtp2go: !vault |
$ANSIBLE_VAULT;1.1;AES256
33313138356235346465333737303766626463636438316366353262356430316636636462613066
3166353663663163306536363536366462633365616161650a613061306630356533343033366333
31643364646665653330326435666366313763633135323063373736666337316130316233396235
3834313832393237650a636138363436376631323338303232356137353063616561313039313130
3236
tasks:
- name: Install podman
ansible.builtin.apt:
name: podman
state: present
- name: Install podman-compose
ansible.builtin.apt:
name: podman-compose
state: present
- name: Stop exim4
ansible.builtin.service:
name: exim4
state: stopped
enabled: false
- name: Create mail directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: '0750'
loop:
- /opt/beeserver/mail
- name: Compose down
changed_when: true
failed_when: false
ansible.builtin.command:
cmd: podman-compose down
chdir: /opt/beeserver/mail
- name: Copy compose
ansible.builtin.template:
src: docker-compose.yml.j2
dest: /opt/beeserver/mail/docker-compose.yml
mode: '0644'
- name: Copy mailserver.env
ansible.builtin.template:
src: mailserver.env.j2
dest: /opt/beeserver/mail/mailserver.env
mode: '0600'
- name: Compose up
changed_when: true
ansible.builtin.command:
cmd: podman-compose up -d
chdir: /opt/beeserver/mail
+663
View File
@@ -0,0 +1,663 @@
# -----------------------------------------------
# --- Mailserver Environment Variables ----------
# -----------------------------------------------
# DOCUMENTATION FOR THESE VARIABLES IS FOUND UNDER
# https://docker-mailserver.github.io/docker-mailserver/latest/config/environment/
# -----------------------------------------------
# --- General Section ---------------------------
# -----------------------------------------------
# **empty** => Internally uses the `hostname --fqdn` command to get the canonical hostname assigned to the DMS container.
# => Specify an FQDN (fully-qualified domain name) to serve mail for. The hostname is required for DMS to function correctly
#
# **WARNING**: Setting OVERRIDE_HOSTNAME can have difficult to predict side effects:
# https://docker-mailserver.github.io/docker-mailserver/latest/config/environment/#override_hostname
OVERRIDE_HOSTNAME=
# Set the log level for DMS.
# This is mostly relevant for container startup scripts and change detection event feedback.
#
# Valid values (in order of increasing verbosity) are: `error`, `warn`, `info`, `debug` and `trace`.
# The default log level is `info`.
LOG_LEVEL=info
# critical => Only show critical messages
# error => Only show erroneous output
# **warn** => Show warnings
# info => Normal informational output
# debug => Also show debug messages
SUPERVISOR_LOGLEVEL=
# Support for deployment where these defaults are not compatible (eg: some NAS appliances):
# /var/mail vmail User ID (default: 5000)
DMS_VMAIL_UID=
# /var/mail vmail Group ID (default: 5000)
DMS_VMAIL_GID=
# **empty** => use FILE
# LDAP => use LDAP authentication
# OIDC => use OIDC authentication (not yet implemented)
# FILE => use local files (this is used as the default)
ACCOUNT_PROVISIONER=
# empty => postmaster@domain.com
# => Specify the postmaster address
POSTMASTER_ADDRESS=postmaster@secretbee.buzz
# Check for updates on container start and then once a day
# If an update is available, a mail is sent to POSTMASTER_ADDRESS
# 0 => Update check disabled
# 1 => Update check enabled
ENABLE_UPDATE_CHECK=1
# Customize the update check interval.
# Number + Suffix. Suffix must be 's' for seconds, 'm' for minutes, 'h' for hours or 'd' for days.
UPDATE_CHECK_INTERVAL=1d
# Set different options for mynetworks option (can be overwrite in postfix-main.cf)
# **WARNING**: Adding the docker network's gateway to the list of trusted hosts, e.g. using the `network` or
# `connected-networks` option, can create an open relay
# https://github.com/docker-mailserver/docker-mailserver/issues/1405#issuecomment-590106498
# The same can happen for rootless podman. To prevent this, set the value to "none" or configure slirp4netns
# https://github.com/docker-mailserver/docker-mailserver/issues/2377
#
# none => Explicitly force authentication
# container => Container IP address only
# host => Add docker container network (ipv4 only)
# network => Add all docker container networks (ipv4 only)
# connected-networks => Add all connected docker networks (ipv4 only)
PERMIT_DOCKER=none
# Set the timezone. If this variable is unset, the container runtime will try to detect the time using
# `/etc/localtime`, which you can alternatively mount into the container. The value of this variable
# must follow the pattern `AREA/ZONE`, i.e. of you want to use Germany's time zone, use `Europe/Berlin`.
# You can lookup all available timezones here: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
TZ=
# In case you network interface differs from 'eth0', e.g. when you are using HostNetworking in Kubernetes,
# you can set NETWORK_INTERFACE to whatever interface you want. This interface will then be used.
# - **empty** => eth0
NETWORK_INTERFACE=
# empty => modern
# modern => Limits the cipher suite to secure ciphers only.
# intermediate => Relaxes security by adding additional ciphers for broader compatibility.
# NOTE: The minimum TLS version supported is 1.2, if you need to lower that follow this workaround advice:
# https://github.com/docker-mailserver/docker-mailserver/pull/2945#issuecomment-1949907964
TLS_LEVEL=
# Configures the handling of creating mails with forged sender addresses.
#
# **0** => (not recommended) Mail address spoofing allowed. Any logged in user may create email messages with a forged sender address (see also https://en.wikipedia.org/wiki/Email_spoofing).
# 1 => Mail spoofing denied. Each user may only send with their own or their alias addresses. Addresses with extension delimiters(http://www.postfix.org/postconf.5.html#recipient_delimiter) are not able to send messages.
SPOOF_PROTECTION=1
# Enables the Sender Rewriting Scheme. SRS is needed if your mail server acts as forwarder. See [postsrsd](https://github.com/roehling/postsrsd/blob/main/README.rst) for further explanation.
# - **0** => Disabled
# - 1 => Enabled
ENABLE_SRS=0
# Enables the OpenDKIM service.
# **1** => Enabled
# 0 => Disabled
ENABLE_OPENDKIM=1
# Enables the OpenDMARC service.
# **1** => Enabled
# 0 => Disabled
ENABLE_OPENDMARC=1
# Enabled `policyd-spf` in Postfix's configuration. You will likely want to set this
# to `0` in case you're using Rspamd (`ENABLE_RSPAMD=1`).
#
# - 0 => Disabled
# - **1** => Enabled
ENABLE_POLICYD_SPF=1
# Enables POP3 service
# - **0** => Disabled
# - 1 => Enabled
ENABLE_POP3=
# Enables IMAP service
# - 0 => Disabled
# - **1** => Enabled
ENABLE_IMAP=1
# Enables ClamAV, and anti-virus scanner.
# 1 => Enabled
# **0** => Disabled
ENABLE_CLAMAV=0
# Add the value of this ENV as a prefix to the mail subject when spam is detected.
# NOTE: This subject prefix may be redundant (by default spam is delivered to a junk folder).
# It provides value when your junk mail is stored alongside legitimate mail instead of a separate location (like with `SPAMASSASSIN_SPAM_TO_INBOX=1` or `MOVE_SPAM_TO_JUNK=0` or a POP3 only setup, without IMAP).
# NOTE: When not using Docker Compose, other CRI may not support quote-wrapping the value here to preserve any trailing white-space.
SPAM_SUBJECT=
# Enables Rspamd
# **0** => Disabled
# 1 => Enabled
ENABLE_RSPAMD=0
# When `ENABLE_RSPAMD=1`, an internal Redis instance is enabled implicitly.
# This setting provides an opt-out to allow using an external instance instead.
# 0 => Disabled
# 1 => Enabled
ENABLE_RSPAMD_REDIS=
# When enabled,
#
# 1. the "[autolearning][rspamd-autolearn]" feature is turned on;
# 2. the Bayes classifier will be trained when moving mails from or to the Junk folder (with the help of Sieve scripts).
#
# **0** => disabled
# 1 => enabled
RSPAMD_LEARN=0
# This settings controls whether checks should be performed on emails coming
# from authenticated users (i.e. most likely outgoing emails). The default value
# is `0` in order to align better with SpamAssassin. We recommend reading
# through https://rspamd.com/doc/tutorials/scanning_outbound.html though to
# decide for yourself whether you need and want this feature.
#
# Note that DKIM signing of e-mails will still happen.
RSPAMD_CHECK_AUTHENTICATED=0
# Controls whether the Rspamd Greylisting module is enabled.
# This module can further assist in avoiding spam emails by greylisting
# e-mails with a certain spam score.
#
# **0** => disabled
# 1 => enabled
RSPAMD_GREYLISTING=0
# Can be used to enable or disable the Hfilter group module.
#
# - 0 => Disabled
# - **1** => Enabled
RSPAMD_HFILTER=1
# Can be used to control the score when the HFILTER_HOSTNAME_UNKNOWN symbol applies. A higher score is more punishing. Setting it to 15 is equivalent to rejecting the email when the check fails.
#
# Default: 6
RSPAMD_HFILTER_HOSTNAME_UNKNOWN_SCORE=6
# Can be used to enable or disable the (still experimental) neural module.
#
# - **0** => Disabled
# - 1 => Enabled
RSPAMD_NEURAL=0
# Amavis content filter (used for ClamAV & SpamAssassin)
# 0 => Disabled
# 1 => Enabled
ENABLE_AMAVIS=0
# -1/-2/-3 => Only show errors
# **0** => Show warnings
# 1/2 => Show default informational output
# 3/4/5 => log debug information (very verbose)
AMAVIS_LOGLEVEL=0
# This enables DNS block lists in Postscreen.
# Note: Emails will be rejected, if they don't pass the block list checks!
# **0** => DNS block lists are disabled
# 1 => DNS block lists are enabled
ENABLE_DNSBL=1
# If you enable Fail2Ban, don't forget to add the following lines to your `compose.yaml`:
# cap_add:
# - NET_ADMIN
# Otherwise, `nftables` won't be able to ban IPs.
ENABLE_FAIL2BAN=0
# Fail2Ban blocktype
# drop => drop packet (send NO reply)
# reject => reject packet (send ICMP unreachable)
FAIL2BAN_BLOCKTYPE=drop
# 1 => Enables Managesieve on port 4190
# empty => disables Managesieve
ENABLE_MANAGESIEVE=
# **enforce** => Allow other tests to complete. Reject attempts to deliver mail with a 550 SMTP reply, and log the helo/sender/recipient information. Repeat this test the next time the client connects.
# drop => Drop the connection immediately with a 521 SMTP reply. Repeat this test the next time the client connects.
# ignore => Ignore the failure of this test. Allow other tests to complete. Repeat this test the next time the client connects. This option is useful for testing and collecting statistics without blocking mail.
POSTSCREEN_ACTION=enforce
# empty => all daemons start
# 1 => only launch postfix smtp
SMTP_ONLY=
# Please read [the SSL page in the documentation](https://docker-mailserver.github.io/docker-mailserver/latest/config/security/ssl) for more information.
#
# empty => SSL disabled
# letsencrypt => Enables Let's Encrypt certificates
# custom => Enables custom certificates
# manual => Let's you manually specify locations of your SSL certificates for non-standard cases
# self-signed => Enables self-signed certificates
SSL_TYPE=letsencrypt
# These are only supported with `SSL_TYPE=manual`.
# Provide the path to your cert and key files that you've mounted access to within the container.
SSL_CERT_PATH=
SSL_KEY_PATH=
# Optional: A 2nd certificate can be supported as fallback (dual cert support), eg ECDSA with an RSA fallback.
# Useful for additional compatibility with older MTA and MUA (eg pre-2015).
SSL_ALT_CERT_PATH=
SSL_ALT_KEY_PATH=
# Set how many days a virusmail will stay on the server before being deleted
# empty => 7 days
VIRUSMAILS_DELETE_DELAY=
# Configure Postfix `virtual_transport` to deliver mail to a different LMTP client (default is a dovecot socket).
# Provide any valid URI. Examples:
#
# empty => `lmtp:unix:/var/run/dovecot/lmtp` (default, configured in Postfix main.cf)
# `lmtp:unix:private/dovecot-lmtp` (use socket)
# `lmtps:inet:<host>:<port>` (secure lmtp with starttls)
# `lmtp:<kopano-host>:2003` (use kopano as mailstore)
POSTFIX_DAGENT=
# Set the mailbox size limit for all users. If set to zero, the size will be unlimited (default). Size is in bytes.
#
# empty => 0
POSTFIX_MAILBOX_SIZE_LIMIT=10737418240
# See https://docker-mailserver.github.io/docker-mailserver/latest/config/account-management/overview/#quotas
# 0 => Dovecot quota is disabled
# 1 => Dovecot quota is enabled
ENABLE_QUOTAS=1
# Set the message size limit for all users. If set to zero, the size will be unlimited (not recommended!). Size is in bytes.
#
# empty => 10240000 (~10 MB)
POSTFIX_MESSAGE_SIZE_LIMIT=
# Mails larger than this limit won't be scanned.
# ClamAV must be enabled (ENABLE_CLAMAV=1) for this.
#
# empty => 25M (25 MB)
CLAMAV_MESSAGE_SIZE_LIMIT=
# Enables regular pflogsumm mail reports.
# This is a new option. The old REPORT options are still supported for backwards compatibility. If this is not set and reports are enabled with the old options, logrotate will be used.
#
# not set => No report
# daily_cron => Daily report for the previous day
# logrotate => Full report based on the mail log when it is rotated
PFLOGSUMM_TRIGGER=
# Recipient address for pflogsumm reports.
#
# not set => Use REPORT_RECIPIENT or POSTMASTER_ADDRESS
# => Specify the recipient address(es)
PFLOGSUMM_RECIPIENT=
# Sender address (`FROM`) for pflogsumm reports if pflogsumm reports are enabled.
#
# not set => Use REPORT_SENDER
# => Specify the sender address
PFLOGSUMM_SENDER=
# Interval for logwatch report.
#
# none => No report is generated
# daily => Send a daily report
# weekly => Send a report every week
LOGWATCH_INTERVAL=
# Recipient address for logwatch reports if they are enabled.
#
# not set => Use REPORT_RECIPIENT or POSTMASTER_ADDRESS
# => Specify the recipient address(es)
LOGWATCH_RECIPIENT=
# Sender address (`FROM`) for logwatch reports if logwatch reports are enabled.
#
# not set => Use REPORT_SENDER
# => Specify the sender address
LOGWATCH_SENDER=
# Defines who receives reports if they are enabled.
# **empty** => ${POSTMASTER_ADDRESS}
# => Specify the recipient address
REPORT_RECIPIENT=
# Defines who sends reports if they are enabled.
# **empty** => mailserver-report@${DOMAINNAME}
# => Specify the sender address
REPORT_SENDER=
# Changes the interval in which log files are rotated
# **weekly** => Rotate log files weekly
# daily => Rotate log files daily
# monthly => Rotate log files monthly
#
# Note: This Variable actually controls logrotate inside the container
# and rotates the log files depending on this setting. The main log output is
# still available in its entirety via `docker logs mail` (Or your
# respective container name). If you want to control logrotation for
# the Docker-generated logfile see:
# https://docs.docker.com/config/containers/logging/configure/
#
# Note: This variable can also determine the interval for Postfix's log summary reports, see [`PFLOGSUMM_TRIGGER`](#pflogsumm_trigger).
LOGROTATE_INTERVAL=weekly
# Defines how many log files are kept by logrorate
LOGROTATE_COUNT=4
# If enabled, employs `reject_unknown_client_hostname` to sender restrictions in Postfix's configuration.
#
# - **0** => Disabled
# - 1 => Enabled
POSTFIX_REJECT_UNKNOWN_CLIENT_HOSTNAME=0
# Choose TCP/IP protocols for postfix to use
# **all** => All possible protocols.
# ipv4 => Use only IPv4 traffic. Most likely you want this behind Docker.
# ipv6 => Use only IPv6 traffic.
#
# Note: More details at http://www.postfix.org/postconf.5.html#inet_protocols
POSTFIX_INET_PROTOCOLS=all
# Enables MTA-STS support for outbound mail.
# More details: https://docker-mailserver.github.io/docker-mailserver/v13.3/config/best-practices/mta-sts/
# - **0** ==> MTA-STS disabled
# - 1 => MTA-STS enabled
ENABLE_MTA_STS=0
# Choose TCP/IP protocols for dovecot to use
# **all** => Listen on all interfaces
# ipv4 => Listen only on IPv4 interfaces. Most likely you want this behind Docker.
# ipv6 => Listen only on IPv6 interfaces.
#
# Note: More information at https://dovecot.org/doc/dovecot-example.conf
DOVECOT_INET_PROTOCOLS=all
# -----------------------------------------------
# --- SpamAssassin Section ----------------------
# -----------------------------------------------
ENABLE_SPAMASSASSIN=0
# KAM is a 3rd party SpamAssassin ruleset, provided by the McGrail Foundation.
# If SpamAssassin is enabled, KAM can be used in addition to the default ruleset.
# - **0** => KAM disabled
# - 1 => KAM enabled
#
# Note: only has an effect if `ENABLE_SPAMASSASSIN=1`
ENABLE_SPAMASSASSIN_KAM=0
# deliver spam messages to the inbox (tagged using SPAM_SUBJECT)
SPAMASSASSIN_SPAM_TO_INBOX=1
# spam messages will be moved in the Junk folder (SPAMASSASSIN_SPAM_TO_INBOX=1 required)
MOVE_SPAM_TO_JUNK=1
# spam messages will be marked as read
MARK_SPAM_AS_READ=0
# add 'spam info' headers at, or above this level
SA_TAG=2.0
# add 'spam detected' headers at, or above this level
SA_TAG2=6.31
# triggers spam evasive actions
SA_KILL=10.0
# -----------------------------------------------
# --- Fetchmail Section -------------------------
# -----------------------------------------------
ENABLE_FETCHMAIL=0
# The interval to fetch mail in seconds
FETCHMAIL_POLL=300
# Use multiple fetchmail instances (1 per poll entry in fetchmail.cf)
# Supports multiple IMAP IDLE connections when a server is used across multiple poll entries
# https://otremba.net/wiki/Fetchmail_(Debian)#Immediate_Download_via_IMAP_IDLE
FETCHMAIL_PARALLEL=0
# Enable or disable `getmail`.
#
# - **0** => Disabled
# - 1 => Enabled
ENABLE_GETMAIL=0
# The number of minutes for the interval. Min: 1; Default: 5.
GETMAIL_POLL=5
# -----------------------------------------------
# --- OAUTH2 Section ----------------------------
# -----------------------------------------------
# empty => OAUTH2 authentication is disabled
# 1 => OAUTH2 authentication is enabled
ENABLE_OAUTH2=
# Specify the user info endpoint URL of the oauth2 provider
# Example: https://oauth2.example.com/userinfo/
OAUTH2_INTROSPECTION_URL=
# -----------------------------------------------
# --- LDAP Section ------------------------------
# -----------------------------------------------
# A second container for the ldap service is necessary (i.e. https://hub.docker.com/r/bitnami/openldap/)
# empty => no
# yes => LDAP over TLS enabled for Postfix
LDAP_START_TLS=
# empty => mail.example.com
# Specify the `<dns-name>` / `<ip-address>` where the LDAP server is reachable via a URI like: `ldaps://mail.example.com`.
# Note: You must include the desired URI scheme (`ldap://`, `ldaps://`, `ldapi://`).
LDAP_SERVER_HOST=
# empty => ou=people,dc=domain,dc=com
# => e.g. LDAP_SEARCH_BASE=dc=mydomain,dc=local
LDAP_SEARCH_BASE=
# empty => cn=admin,dc=domain,dc=com
# => take a look at examples of SASL_LDAP_BIND_DN
LDAP_BIND_DN=
# empty** => admin
# => Specify the password to bind against ldap
LDAP_BIND_PW=
# e.g. `"(&(mail=%s)(mailEnabled=TRUE))"`
# => Specify how ldap should be asked for users
LDAP_QUERY_FILTER_USER=
# e.g. `"(&(mailGroupMember=%s)(mailEnabled=TRUE))"`
# => Specify how ldap should be asked for groups
LDAP_QUERY_FILTER_GROUP=
# e.g. `"(&(mailAlias=%s)(mailEnabled=TRUE))"`
# => Specify how ldap should be asked for aliases
LDAP_QUERY_FILTER_ALIAS=
# e.g. `"(&(|(mail=*@%s)(mailalias=*@%s)(mailGroupMember=*@%s))(mailEnabled=TRUE))"`
# => Specify how ldap should be asked for domains
LDAP_QUERY_FILTER_DOMAIN=
# -----------------------------------------------
# --- Dovecot Section ---------------------------
# -----------------------------------------------
# empty => no
# yes => LDAP over TLS enabled for Dovecot
DOVECOT_TLS=
# e.g. `"(&(objectClass=PostfixBookMailAccount)(uniqueIdentifier=%n))"`
DOVECOT_USER_FILTER=
# e.g. `"(&(objectClass=PostfixBookMailAccount)(uniqueIdentifier=%n))"`
DOVECOT_PASS_FILTER=
# Define the mailbox format to be used
# default is maildir, supported values are: sdbox, mdbox, maildir
DOVECOT_MAILBOX_FORMAT=maildir
# empty => no
# yes => Allow bind authentication for LDAP
# https://doc.dovecot.org/2.4.0/core/config/auth/databases/ldap.html#authentication-bind
DOVECOT_AUTH_BIND=
# -----------------------------------------------
# --- Postgrey Section --------------------------
# -----------------------------------------------
ENABLE_POSTGREY=0
# greylist for N seconds
POSTGREY_DELAY=300
# delete entries older than N days since the last time that they have been seen
POSTGREY_MAX_AGE=35
# response when a mail is greylisted
POSTGREY_TEXT="Delayed by Postgrey"
# whitelist host after N successful deliveries (N=0 to disable whitelisting)
POSTGREY_AUTO_WHITELIST_CLIENTS=5
# -----------------------------------------------
# --- SASL Section ------------------------------
# -----------------------------------------------
ENABLE_SASLAUTHD=0
# empty => ldap
# `ldap` => authenticate against ldap server
# `rimap` => authenticate against imap server
SASLAUTHD_MECHANISMS=
# empty => None
# e.g. with SASLAUTHD_MECHANISMS rimap you need to specify the ip-address/servername of the imap server ==> xxx.xxx.xxx.xxx
SASLAUTHD_MECH_OPTIONS=
# empty => Use value of LDAP_SERVER_HOST
# Note: You must include the desired URI scheme (`ldap://`, `ldaps://`, `ldapi://`).
SASLAUTHD_LDAP_SERVER=
# empty => Use value of LDAP_BIND_DN
# specify an object with privileges to search the directory tree
# e.g. active directory: SASLAUTHD_LDAP_BIND_DN=cn=Administrator,cn=Users,dc=mydomain,dc=net
# e.g. openldap: SASLAUTHD_LDAP_BIND_DN=cn=admin,dc=mydomain,dc=net
SASLAUTHD_LDAP_BIND_DN=
# empty => Use value of LDAP_BIND_PW
SASLAUTHD_LDAP_PASSWORD=
# empty => Use value of LDAP_SEARCH_BASE
# specify the search base
SASLAUTHD_LDAP_SEARCH_BASE=
# empty => default filter `(&(uniqueIdentifier=%u)(mailEnabled=TRUE))`
# e.g. for active directory: `(&(sAMAccountName=%U)(objectClass=person))`
# e.g. for openldap: `(&(uid=%U)(objectClass=person))`
SASLAUTHD_LDAP_FILTER=
# empty => no
# yes => LDAP over TLS enabled for SASL
# If set to yes, the protocol in SASLAUTHD_LDAP_SERVER must be ldap:// or missing.
SASLAUTHD_LDAP_START_TLS=
# empty => no
# yes => Require and verify server certificate
# If yes you must/could specify SASLAUTHD_LDAP_TLS_CACERT_FILE or SASLAUTHD_LDAP_TLS_CACERT_DIR.
SASLAUTHD_LDAP_TLS_CHECK_PEER=
# File containing CA (Certificate Authority) certificate(s).
# empty => Nothing is added to the configuration
# Any value => Fills the `ldap_tls_cacert_file` option
SASLAUTHD_LDAP_TLS_CACERT_FILE=
# Path to directory with CA (Certificate Authority) certificates.
# empty => Nothing is added to the configuration
# Any value => Fills the `ldap_tls_cacert_dir` option
SASLAUTHD_LDAP_TLS_CACERT_DIR=
# Specify what password attribute to use for password verification.
# empty => Nothing is added to the configuration but the documentation says it is `userPassword` by default.
# Any value => Fills the `ldap_password_attr` option
SASLAUTHD_LDAP_PASSWORD_ATTR=
# empty => `bind` will be used as a default value
# `fastbind` => The fastbind method is used
# `custom` => The custom method uses userPassword attribute to verify the password
SASLAUTHD_LDAP_AUTH_METHOD=
# Specify the authentication mechanism for SASL bind
# empty => Nothing is added to the configuration
# Any value => Fills the `ldap_mech` option
SASLAUTHD_LDAP_MECH=
# -----------------------------------------------
# --- SRS Section -------------------------------
# -----------------------------------------------
# envelope_sender => Rewrite only envelope sender address (default)
# header_sender => Rewrite only header sender (not recommended)
# envelope_sender,header_sender => Rewrite both senders
# An email has an "envelope" sender (indicating the sending server) and a
# "header" sender (indicating who sent it). More strict SPF policies may require
# you to replace both instead of just the envelope sender.
SRS_SENDER_CLASSES=envelope_sender
# empty => Envelope sender will be rewritten for all domains
# provide comma separated list of domains to exclude from rewriting
SRS_EXCLUDE_DOMAINS=
# empty => generated when the image is built
# provide a secret to use in base64
# you may specify multiple keys, comma separated. the first one is used for
# signing and the remaining will be used for verification. this is how you
# rotate and expire keys
SRS_SECRET=
# -----------------------------------------------
# --- Default Relay Host Section ----------------
# -----------------------------------------------
# Setup relaying all mail through a default relay host
#
# Set a default host to relay all mail through (optionally include a port)
# Example: [mail.example.com]:587
#DEFAULT_RELAY_HOST=[email-smtp.eu-north-1.amazonaws.com]:587
DEFAULT_RELAY_HOST=[mail-eu.smtp2go.com]:2525
# -----------------------------------------------
# --- Multi-Domain Relay Section ----------------
# -----------------------------------------------
# Setup relaying for multiple domains based on the domain name of the sender
# optionally uses usernames and passwords in postfix-sasl-password.cf and relay host mappings in postfix-relaymap.cf
#
# Set a default host to relay mail through
# Example: mail.example.com
#RELAY_HOST=email-smtp.eu-north-1.amazonaws.com
RELAY_HOST=
# empty => 25
# default port to relay mail
#RELAY_PORT=587
RELAY_PORT=
# -----------------------------------------------
# --- Relay Host Credentials Section ------------
# -----------------------------------------------
# Configure a relay user and password to use with RELAY_HOST / DEFAULT_RELAY_HOST
# empty => no default
RELAY_USER={{ relay_user_smtp2go }}
# empty => no default
RELAY_PASSWORD={{ relay_password_smtp2go }}
+25
View File
@@ -0,0 +1,25 @@
services:
homeserver:
image: "forgejo.ellis.link/continuwuation/continuwuity:latest"
restart: always
command: /sbin/conduwuit
ports:
- 127.0.0.1:8008:8008
volumes:
- db:/var/lib/continuwuity
- /opt/beeserver/matrix/resolv.conf:/etc/resolv.conf
#- ./continuwuity.toml:/etc/continuwuity.toml
environment:
CONTINUWUITY_SERVER_NAME: secretbee.buzz
CONTINUWUITY_DATABASE_PATH: /var/lib/continuwuity
CONTINUWUITY_ADDRESS: 0.0.0.0
CONTINUWUITY_PORT: 8008
#CONTINUWUITY_CONFIG: '/etc/continuwuity.toml' # Uncomment if you mapped config toml above
#CONTINUWUITY_WELL_KNOWN: |
# {
# client=https://secretbee.buzz,
# server=secretbee.buzz:443
# }
volumes:
db:
+47
View File
@@ -0,0 +1,47 @@
- name: Matrix
hosts: beepi
become: true
tasks:
- name: Install podman
ansible.builtin.apt:
name: podman
state: present
- name: Install podman-compose
ansible.builtin.apt:
name: podman-compose
state: present
- name: Create matrix directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: '0755'
loop:
- /opt/beeserver/matrix
- name: Compose down
changed_when: true
failed_when: false
ansible.builtin.command:
cmd: podman-compose down
chdir: /opt/beeserver/matrix
- name: Copy resolv.conf
ansible.builtin.template:
src: resolv.conf.j2
dest: /opt/beeserver/matrix/resolv.conf
mode: '0644'
- name: Copy compose
ansible.builtin.template:
src: docker-compose.yml.j2
dest: /opt/beeserver/matrix/docker-compose.yml
mode: '0644'
- name: Compose up
changed_when: true
ansible.builtin.command:
cmd: podman-compose up -d
chdir: /opt/beeserver/matrix
+2
View File
@@ -0,0 +1,2 @@
nameserver 1.0.0.1
nameserver 1.1.1.1
+61
View File
@@ -0,0 +1,61 @@
loki.source.journal "system" {
forward_to = [loki.write.default.receiver]
labels = {
job = "systemd-journal",
host = "beepi",
}
}
local.file_match "fail2ban" {
path_targets = [{"__path__" = "/var/log/fail2ban.log", job = "fail2ban", host = "beepi"}]
}
local.file_match "varlog" {
path_targets = [{"__path__" = "/var/log/*.log", job = "varlog", "__path_exclude__" = "/var/log/fail2ban.log", host = "beepi"}]
}
loki.source.file "varlog" {
targets = local.file_match.varlog.targets
forward_to = [loki.write.default.receiver]
}
loki.source.file "fail2ban_source" {
targets = local.file_match.fail2ban.targets
forward_to = [loki.process.geoip.receiver]
}
loki.process "geoip" {
forward_to = [loki.write.default.receiver]
stage.regex {
expression = `^.*:\s(?<level>\w*)\s*\[(?<service>\w*)\]\s(?<type>\w*)\s(?<ip>(?:(?:2(?:[0-4][0-9]|5[0-5])|[0-1]?[0-9]?[0-9])\.){3}(?:(?:2([0-4][0-9]|5[0-5])|[0-1]?[0-9]?[0-9]))).*$`
labels_from_groups = true
}
stage.geoip {
db = "/opt/database/GeoLite2-City.mmdb"
source = "ip"
db_type = "city"
}
stage.labels {
values = {
geoip_city_name = "",
geoip_country_name = "",
geoip_country_code = "",
geoip_continent_name = "",
geoip_continent_code = "",
geoip_location_latitude = "",
geoip_location_longitude = "",
geoip_postal_code = "",
geoip_timezone = "",
geoip_subdivision_name = "",
geoip_subdivision_code = "",
}
}
}
loki.write "default" {
endpoint {
url = "http://loki:3100/loki/api/v1/push"
}
}
+64 -4
View File
@@ -6,21 +6,21 @@ services:
prometheus: prometheus:
image: docker.io/prom/prometheus image: docker.io/prom/prometheus
container_name: prometheus container_name: prometheus
restart: unless-stopped restart: always
ports: ports:
- '127.0.0.1:9090:9090' - '127.0.0.1:9090:9090'
volumes: volumes:
- prometheus-data:/prometheus - prometheus-data:/prometheus
- /opt/monitoring/prometheus.yml:/etc/prometheus/prometheus.yml - /opt/beeserver/monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
networks: networks:
- monitoring - monitoring
grafana: grafana:
image: docker.io/grafana/grafana image: docker.io/grafana/grafana
container_name: grafana container_name: grafana
restart: unless-stopped restart: always
ports: ports:
- '4000:4000' - '127.0.0.1:4000:4000'
volumes: volumes:
- grafana-storage:/var/lib/grafana - grafana-storage:/var/lib/grafana
environment: environment:
@@ -31,3 +31,63 @@ services:
- GF_SERVER_PROTOCOL=HTTP - GF_SERVER_PROTOCOL=HTTP
networks: networks:
- monitoring - monitoring
loki:
image: docker.io/grafana/loki
container_name: loki
ports:
- '127.0.0.1:3100:3100'
- '127.0.0.1:9096:9096'
volumes:
- loki-data:/loki
- /opt/beeserver/monitoring/local-config.yml:/etc/loki/local-config.yaml
command: -config.file=/etc/loki/local-config.yaml
restart: always
networks:
- monitoring
alloy:
image: docker.io/grafana/alloy
container_name: alloy
ports:
- '127.0.0.1:12345:12345'
volumes:
- /opt/beeserver/monitoring/config.alloy:/etc/alloy/config.alloy
- /opt/beeserver/monitoring/database:/opt/database
- /var/log:/var/log:ro
- /run/log/journal:/run/log/journal:ro
- /var/log/journal:/var/log/journal:ro
- /etc/machine-id:/etc/machine-id:ro
- alloy-data:/var/lib/alloy/data
command:
- run
- /etc/alloy/config.alloy
- --storage.path=/var/lib/alloy/data
- --server.http.listen-addr=0.0.0.0:12345
- --stability.level=experimental
networks:
- monitoring
restart: always
podman-exporter:
image: quay.io/navidys/prometheus-podman-exporter
container_name: podman-exporter
restart: always
privileged: true
user: root
ports:
- '127.0.0.1:9882:9882'
volumes:
- /run/podman/podman.sock:/run/podman/podman.sock
environment:
- CONTAINER_HOST=unix:///run/podman/podman.sock
security_opt:
- label=disable
networks:
- monitoring
volumes:
prometheus-data:
grafana-storage:
loki-data:
alloy-data:
+78
View File
@@ -0,0 +1,78 @@
auth_enabled: false
server:
http_listen_port: 3100
grpc_listen_port: 9096
log_level: info
common:
instance_addr: 127.0.0.1
path_prefix: /loki
storage:
filesystem:
chunks_directory: /loki/chunks
rules_directory: /loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemory
query_range:
results_cache:
cache:
embedded_cache:
enabled: true
max_size_mb: 100
schema_config:
configs:
- from: 2020-10-24
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
ruler:
alertmanager_url: http://localhost:9093
ingester:
wal:
enabled: true
dir: /loki/wal
lifecycler:
ring:
replication_factor: 1
limits_config:
retention_period: 30d
reject_old_samples: true
reject_old_samples_max_age: 168h
ingestion_rate_mb: 16
ingestion_burst_size_mb: 24
max_streams_per_user: 10000
max_line_size: 256kb
chunk_store_config:
chunk_cache_config:
embedded_cache:
enabled: true
max_size_mb: 100
storage_config:
tsdb_shipper:
active_index_directory: /loki/tsdb-index
cache_location: /loki/tsdb-cache
compactor:
working_directory: /loki/compactor
compaction_interval: 10m
retention_enabled: true
retention_delete_delay: 2h
retention_delete_worker_count: 150
delete_request_store: filesystem
table_manager:
retention_deletes_enabled: true
retention_period: 720h
+85 -15
View File
@@ -1,5 +1,5 @@
- name: Prometheus - name: Prometheus
hosts: pi hosts: beepi
become: true become: true
vars: vars:
grafana_secret: !vault | grafana_secret: !vault |
@@ -9,6 +9,21 @@
36346437353963333839656163623933616662326132373036636166616538343966356361636164 36346437353963333839656163623933616662326132373036636166616538343966356361636164
3035656163616631330a663363343363643065356535356633623638376430326539363536666638 3035656163616631330a663363343363643065356535356633623638376430326539363536666638
65333930613135333364383462363233386662386531323935353932373465363234 65333930613135333364383462363233386662386531323935353932373465363234
geoip_username: !vault |
$ANSIBLE_VAULT;1.1;AES256
30656365643463396265633130356339386433633331613130633134336633643637653761623962
3633336466326564616432373031303530376166353436610a323033353164313436613363613836
30303931323234306162343361643162313238313234383837323530343936343134326365666166
3438643238626266320a333732363461613834613833303436363534393031323333613534333534
3438
geoip_license: !vault |
$ANSIBLE_VAULT;1.1;AES256
32336437653435396231663666643631373638616533653538333934356339666661313439343566
6462303439666233316162653430363239393031633362630a323533393233633164613031646633
62366362383162306563383235373262326262323337303333313163653838613436316337633063
3630356262666338320a333137333063303534386437343762616665383034336365663732343566
36376463313964333834373435653564346333396538306337333762613737643363636364353139
3032383564333638613566633363666430356230326231633636
tasks: tasks:
- name: Install podman - name: Install podman
ansible.builtin.apt: ansible.builtin.apt:
@@ -25,32 +40,87 @@
name: prometheus-node-exporter name: prometheus-node-exporter
state: present state: present
- name: Create prometheus config directory - name: Create monitoring config directory
ansible.builtin.file: ansible.builtin.file:
path: /opt/monitoring path: /opt/beeserver/monitoring
state: directory state: directory
mode: '0755' mode: '0755'
- name: Copy config - name: Compose down
ansible.builtin.copy: changed_when: true
src: prometheus_config.yml failed_when: false
dest: /opt/monitoring/prometheus.yml ansible.builtin.command:
mode: '0644' cmd: podman-compose down
chdir: /opt/beeserver/monitoring
- name: Copy compose - name: Copy compose
ansible.builtin.template: ansible.builtin.template:
src: docker-compose.yml.j2 src: docker-compose.yml.j2
dest: /opt/monitoring/docker-compose.yml dest: /opt/beeserver/monitoring/docker-compose.yml
mode: '0644' mode: '0644'
- name: Compose down - name: Copy prometheus config
changed_when: true ansible.builtin.copy:
ansible.builtin.command: src: prometheus_config.yml
cmd: podman-compose down dest: /opt/beeserver/monitoring/prometheus.yml
chdir: /opt/monitoring mode: '0644'
- name: Copy loki config
ansible.builtin.template:
src: local-config.yml.j2
dest: /opt/beeserver/monitoring/local-config.yml
mode: '0644'
- name: Copy alloy config
ansible.builtin.template:
src: config.alloy.j2
dest: /opt/beeserver/monitoring/config.alloy
mode: '0644'
- name: Enable podman.socket
ansible.builtin.service:
name: podman.socket
state: started
enabled: true
- name: Delete database directory
ansible.builtin.file:
path: /opt/beeserver/monitoring/database
state: absent
mode: '0755'
- name: Create database directory
ansible.builtin.file:
path: /opt/beeserver/monitoring/database
state: directory
mode: '0755'
- name: Download geoip database
ansible.builtin.get_url:
url: "https://download.maxmind.com/geoip/databases/GeoLite2-City/download?suffix=tar.gz"
dest: /opt/beeserver/monitoring
username: "{{ geoip_username }}"
password: "{{ geoip_license }}"
mode: '0644'
- name: Get geoip tar file
ansible.builtin.find:
paths: /opt/beeserver/monitoring
file_type: file
patterns: '^GeoLite.*.tar.gz$'
use_regex: true
limit: 1
register: found
- name: Extract geopip database
ansible.builtin.unarchive:
remote_src: true
src: "{{ found.files[0].path }}"
dest: /opt/beeserver/monitoring/database
extra_opts: ['--strip-components=1', '--show-stored-names']
- name: Compose up - name: Compose up
changed_when: true changed_when: true
ansible.builtin.command: ansible.builtin.command:
cmd: podman-compose up -d cmd: podman-compose up -d
chdir: /opt/monitoring chdir: /opt/beeserver/monitoring
+6 -1
View File
@@ -8,4 +8,9 @@ scrape_configs:
- targets: ['localhost:9090'] - targets: ['localhost:9090']
- job_name: node - job_name: node
static_configs: static_configs:
- targets: ['host.containers.internal:9100'] - targets:
- 'host.containers.internal:9100'
- '192.168.178.51:9100'
- job_name: podman
static_configs:
- targets: ['podman-exporter:9882']
-16
View File
@@ -1,16 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Secretbee</title>
<link rel="icon" type="image/x-icon" href="/icon.ico">
</head>
<body>
<p><img src="https://secretbee.buzz/icon.png" alt="bee" width="128" height="128" /></p>
<p>Welcome to the hive.</p>
<p>Available services:</p>
<p>&nbsp;</p>
<h1><strong>irc</strong></h1>
<p>Grab yourself an irc client (for example <a href="https://www.mirc.com/">mirc</a>) and connect to irc.secretbee.buzz and port 6697.</p>
<p>All traffic is encrypted and secured.</p>
</body>
</html>
+17 -1
View File
@@ -1,5 +1,5 @@
- name: Nginx - name: Nginx
hosts: pi hosts: beepi
become: true become: true
tasks: tasks:
- name: Install nginx - name: Install nginx
@@ -20,6 +20,22 @@
group: root group: root
mode: '0644' mode: '0644'
- name: Copy upstream.conf
ansible.builtin.copy:
src: upstream.conf
dest: /etc/nginx/conf.d/upstream.conf
owner: root
group: root
mode: '0644'
- name: Copy html content
ansible.builtin.copy:
src: www/
dest: /var/www
owner: www-data
group: www-data
mode: '0644'
- name: Restart nginx - name: Restart nginx
ansible.builtin.service: ansible.builtin.service:
name: nginx name: nginx
@@ -0,0 +1,54 @@
server {
listen 80;
server_name gallery.secretbee.buzz;
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name gallery.secretbee.buzz;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
ssl_certificate /etc/letsencrypt/live/gallery.secretbee.buzz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/gallery.secretbee.buzz/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# allow large file uploads
client_max_body_size 50000M;
# disable buffering uploads to prevent OOM on reverse proxy server and make uploads twice as fast (no pause)
proxy_request_buffering off;
# increase body buffer to avoid limiting upload speed
client_body_buffer_size 1024k;
# Set headers
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# enable websockets: http://nginx.org/en/docs/http/websocket.html
proxy_http_version 1.1;
proxy_redirect off;
# set timeout
proxy_read_timeout 600s;
proxy_send_timeout 600s;
send_timeout 600s;
location / {
proxy_pass http://localhost:2283;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /siri {
return 301 https://gallery.secretbee.buzz/s/siri;
}
}
@@ -13,7 +13,7 @@ server {
limit_req zone=mylimit burst=20; limit_req zone=mylimit burst=20;
add_header Strict-Transport-Security "max-age=31536000, includeSubDomains" always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
ssl_certificate /etc/letsencrypt/live/git.secretbee.buzz/fullchain.pem; ssl_certificate /etc/letsencrypt/live/git.secretbee.buzz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/git.secretbee.buzz/privkey.pem; ssl_certificate_key /etc/letsencrypt/live/git.secretbee.buzz/privkey.pem;
@@ -22,7 +22,7 @@ server {
limit_req zone=mylimit burst=20; limit_req zone=mylimit burst=20;
add_header Strict-Transport-Security "max-age=31536000, includeSubDomains" always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
ssl_certificate /etc/letsencrypt/live/grafana.secretbee.buzz/fullchain.pem; ssl_certificate /etc/letsencrypt/live/grafana.secretbee.buzz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/grafana.secretbee.buzz/privkey.pem; ssl_certificate_key /etc/letsencrypt/live/grafana.secretbee.buzz/privkey.pem;
@@ -13,7 +13,7 @@ server {
limit_req zone=mylimit burst=20; limit_req zone=mylimit burst=20;
add_header Strict-Transport-Security "max-age=31536000, includeSubDomains" always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
ssl_certificate /etc/letsencrypt/live/lounge.secretbee.buzz/fullchain.pem; ssl_certificate /etc/letsencrypt/live/lounge.secretbee.buzz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/lounge.secretbee.buzz/privkey.pem; ssl_certificate_key /etc/letsencrypt/live/lounge.secretbee.buzz/privkey.pem;
@@ -0,0 +1,33 @@
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
listen 8448 ssl http2;
listen [::]:8448 ssl http2;
server_name matrix.secretbee.buzz;
ssl_certificate /etc/letsencrypt/live/matrix.secretbee.buzz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/matrix.secretbee.buzz/privkey.pem;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options DENY;
add_header X-XSS-Protection "1; mode=block";
proxy_buffering off;
gzip on;
gzip_types application/json;
gzip_min_length 1000;
location /_matrix/ {
proxy_pass http://continuwuity_server;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
}
}
@@ -0,0 +1,33 @@
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl http2;
server_name ott.secretbee.buzz;
ssl_certificate /etc/letsencrypt/live/ott.secretbee.buzz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ott.secretbee.buzz/privkey.pem;
#deny all;
location / {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_cache_bypass $http_upgrade;
proxy_pass_header Set-Cookie;
# optional, but recommended if you have problem with clients disconnecting and reconnecting frequently
proxy_connect_timeout 7d;
proxy_read_timeout 7d;
proxy_send_timeout 7d;
proxy_socket_keepalive on;
}
}
@@ -1,5 +1,10 @@
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s; limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
map $http_user_agent $link_preview_bot {
default 0;
"~*(Discordbot|Twitterbot|facebookexternalhit|Facebot|Slackbot|TelegramBot|WhatsApp|LinkedInBot|Pinterest|redditbot|Iframely|vkShare|SkypeUriPreview|Mastodon|Googlebot|bingbot)" 1;
}
server { server {
listen 80 default_server; listen 80 default_server;
server_name secretbee.buzz; server_name secretbee.buzz;
@@ -12,6 +17,7 @@ server {
server { server {
listen 443 ssl; listen 443 ssl;
listen [::]:443 ssl http2;
server_name secretbee.buzz; server_name secretbee.buzz;
limit_req zone=mylimit burst=20; limit_req zone=mylimit burst=20;
@@ -25,8 +31,34 @@ server {
ssl_protocols TLSv1.2 TLSv1.3; ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5; ssl_ciphers HIGH:!aNULL:!MD5;
location /.well-known/matrix/server {
default_type application/json;
add_header Access-Control-Allow-Origin "*";
return 200 '{"m.server": "matrix.secretbee.buzz:443"}';
}
location /.well-known/matrix/client {
default_type application/json;
add_header Access-Control-Allow-Origin "*";
return 200 '{"m.homeserver": {"base_url": "https://matrix.secretbee.buzz"}, "org.matrix.msc3575.proxy": {"url": "https://matrix.secretbee.buzz"}}';
}
# Matrix Support contact information (MSC1929)
location /.well-known/matrix/support {
default_type application/json;
add_header Access-Control-Allow-Origin "*";
return 200 '{"contacts": [{"matrix_id": "@admin:secretbee.buzz", "email_address": "admin@server.name", "role": "m.role.admin"}]}';
}
location / { location / {
default_type "text/html"; default_type "text/html";
try_files $uri $uri.html $uri/index.html index.html; try_files $uri $uri.html $uri/index.html index.html;
} }
location = /siri {
if ($link_preview_bot) {
rewrite ^ /siri.html last;
}
return 301 https://gallery.secretbee.buzz/s/siri;
}
} }
+8
View File
@@ -0,0 +1,8 @@
upstream continuwuity_server {
server 127.0.0.1:8008 max_fails=0;
keepalive 32;
keepalive_requests 1000;
keepalive_time 1h;
keepalive_timeout 600s;
}

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

+18
View File
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<title>Secretbee</title>
<link rel="icon" type="image/x-icon" href="/icon.ico">
</head>
<body>
<p><img src="https://secretbee.buzz/icon.png" alt="bee" width="128" height="128" /></p>
<p>Welcome to the hive.</p>
<p>Available services:</p>
<p>&nbsp;</p>
<h1><strong>matrix</strong></h1>
<p>You can reach me at <strong>@happybee:secretbee.buzz</strong>. If you want access to my matrix homeserver, send me a mail.</p>
<h1><strong>mail</strong></h1>
<p>Send whatever nonsense comes to your mind to<strong> bee at secretbee dot buzz</strong></p>
<p>&nbsp;</p>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 428 KiB

+28
View File
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en" prefix="og: https://ogp.me/ns#">
<head>
<title>Siri References</title>
<meta charset="utf-8">
<meta name="theme-color" content="#f54927">
<!-- Facebook -->
<meta property="og:type" content="website">
<meta property="og:title" content="Siri References">
<meta property="og:description" content="All the official Siri references.">
<meta property="og:site_name" content="secretbee.buzz">
<meta property="og:url" content="https://secretbee.buzz/siri">
<meta property="og:image" content="https://secretbee.buzz/siri-cover.png">
<meta name="twitter:card" content="summary_large_image">
<meta property="twitter:domain" content="secretbee.buzz">
<meta property="twitter:url" content="https://secretbee.buzz/siri">
<meta name="twitter:title" content="Siri References">
<meta name="twitter:description" content="All the official Siri references.">
<meta name="twitter:image" content="https://secretbee.buzz/siri-cover.png">
<link rel="canonical" href="https://secretbee.buzz/siri">
</head>
<body>
<p><a href="https://gallery.secretbee.buzz/s/siri">View the gallery →</a></p>
</body>
</html>
+59
View File
@@ -0,0 +1,59 @@
version: "3.7"
services:
opentogethertube:
image: dyc3/opentogethertube:latest
container_name: opentogethertube
environment:
- PORT=8080
- REDIS_HOST=redis_db
- REDIS_PORT=6379
- FFPROBE_PATH=/usr/bin/ffprobe
# postgres
- POSTGRES_USER=opentogethertube
- POSTGRES_DB=opentogethertube
- POSTGRES_HOST=postgres_db
- POSTGRES_PASSWORD=postgres
- DOCKER=1
volumes:
- ./env:/app/env
ports:
- 8080:8080
links:
- redis_db
- postgres_db
depends_on:
- redis_db
- postgres_db
redis_db:
container_name: opentogethertube_redis
image: redis
healthcheck:
test: "redis-cli ping"
expose:
- 6379
volumes:
- db-data-redis:/data
restart: "${DOCKER_RESTART_POLICY:-unless-stopped}"
postgres_db:
container_name: opentogethertube_postgres
image: postgres:15-bullseye
environment:
- POSTGRES_DB=opentogethertube
- POSTGRES_USER=opentogethertube
- POSTGRES_PASSWORD=postgres
healthcheck:
test: "pg_isready -U opentogethertube"
expose:
- 5432
volumes:
- db-data-postgres:/var/lib/postgresql/data
restart: "${DOCKER_RESTART_POLICY:-unless-stopped}"
# shared volume
volumes:
db-data-redis:
driver: local
db-data-postgres:
driver: local
+18
View File
@@ -0,0 +1,18 @@
[Unit]
Description=OpenTogetherTube Postgres
[Container]
ContainerName=ott-db
Image=docker.io/library/postgres:15-bullseye
Network=ott.network
Volume=/home/ott/data/postgres:/var/lib/postgresql/data
Environment=POSTGRES_USER=opentogethertube
Environment=POSTGRES_PASSWORD={{ ott_db_password }}
Environment=POSTGRES_DB=opentogethertube
HealthCmd=pg_isready -U opentogethertube
[Service]
Restart=on-failure
[Install]
WantedBy=default.target
+20
View File
@@ -0,0 +1,20 @@
[Unit]
Description=OpenTogetherTube Redis
[Container]
ContainerName=ott-redis
Image=docker.io/library/redis:7-alpine
Network=ott.network
# Run as the in-image redis uid/gid (999) and let Podman chown the bind-mount
# source to the matching mapped host uid (:U). Without this, redis-server drops
# to the redis user but /data stays root-owned in the userns, so RDB saves fail
# with EPERM.
User=999:999
Volume=/home/ott/data/redis:/data:U
HealthCmd=redis-cli ping
[Service]
Restart=on-failure
[Install]
WantedBy=default.target
+28
View File
@@ -0,0 +1,28 @@
[Unit]
Description=OpenTogetherTube Server
Requires=ott-db.service ott-redis.service
After=ott-db.service ott-redis.service
[Container]
ContainerName=ott-server
Image=git.secretbee.buzz/bee/ott:latest
Network=ott.network
PublishPort=127.0.0.1:8080:8080
Volume=/home/ott/data/env:/app/env
Environment=PORT=8080
Environment=DOCKER=1
Environment=FFPROBE_PATH=/usr/bin/ffprobe
Environment=REDIS_HOST=ott-redis
Environment=REDIS_PORT=6379
Environment=DB_MODE=postgres
Environment=POSTGRES_HOST=ott-db
Environment=POSTGRES_PORT=5432
Environment=POSTGRES_DB=opentogethertube
Environment=POSTGRES_USER=opentogethertube
Environment=POSTGRES_PASSWORD={{ ott_db_password }}
[Service]
Restart=on-failure
[Install]
WantedBy=default.target
+157
View File
@@ -0,0 +1,157 @@
- name: OpenTogetherTube
hosts: beepi
become: true
vars:
user: ott
user_home: /home/ott
ott_db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
33383832303231323133626563623336323137383136623335653063623365616334613338373832
3862613733313565343164383437373165343134303637620a386438383839623431363163366137
31653061353731346261383565373433623938383033306332303035323762353761393435306661
6332663866323861330a653634666464316539396665626366386565306233346563303839616639
61363334373265633930636635663339343461383061353963633762326664376464
ott_api_key: !vault |
$ANSIBLE_VAULT;1.1;AES256
66616532636462386435626536656136366664643539653639393931653337303061326139356138
3665663430643332653931646637373733376639363262360a396430633663623135383731396430
34666563333239326131623337653765633132383136633231393561326566326536663135333035
3937626134376264340a323437626435373330376636353538653736376432643261393364303434
38656639303335633534613832313334373762336364343163623338393037323933343134366238
3532356231333830373063313936373830393035643731653735
google_api_key: !vault |
$ANSIBLE_VAULT;1.1;AES256
65336339346437343062633462393630356139623334353033653937306631336661383138613538
3735333930613365326366393461343462656530616462350a613636623738653232373266303031
36643835383361386161323431323562346666366236666163643936613538616633303663323132
3063366466353937390a633162663635373962313464363166653339353662613162376534623634
66336137383963326461306530636439376465646633356139333739333536396639373861613866
3862376437303236373564393461336263346634393834376562
ott_session_secret: !vault |
$ANSIBLE_VAULT;1.1;AES256
34376530366330626433306637633034663237326234373738613934356131386466323530303333
6264303933366264623564316638383365643134663437650a326165383538376636323237663962
36366362663930633231346230643132386565373733633262303234326636373864626362393031
6534313162396137630a326532663037323161316339643163366532626632336632616535303734
37356562626337366638313666326135343837323665343233363833663961373939336562343462
31323638383336313466643137643037343265613534333963366336666133303031316231313061
63376166666261316436356435623365343335643133326465386239396136363739366635653037
33363965666364376364393132643562633831316361346562386662666637343263363064346136
6162
tasks:
- name: Install dependencies
ansible.builtin.apt:
name: "{{ item }}"
state: present
loop:
- podman
- systemd-container
- passt
- name: Create user
ansible.builtin.user:
name: "{{ user }}"
home: "{{ user_home }}"
shell: /usr/sbin/nologin
create_home: true
register: user_info
- name: Enable linger
ansible.builtin.command:
cmd: "loginctl enable-linger {{ user }}"
creates: "/var/lib/systemd/linger/{{ user }}"
- name: Create quadlet directory
ansible.builtin.file:
path: "{{ user_home }}/.config/containers/systemd"
state: directory
owner: "{{ user }}"
group: "{{ user }}"
mode: '0755'
- name: Create data directories
ansible.builtin.file:
path: "{{ user_home }}/data/{{ item }}"
state: directory
owner: "{{ user }}"
group: "{{ user }}"
mode: '0755'
loop:
- postgres
- redis
- env
- name: Copy production.toml
ansible.builtin.template:
src: production.toml.j2
dest: "{{ user_home }}/data/env/production.toml"
owner: "{{ user }}"
group: "{{ user }}"
mode: '0600'
- name: Copy network
ansible.builtin.copy:
dest: "{{ user_home }}/.config/containers/systemd/ott.network"
content: "[Network]\n"
owner: "{{ user }}"
group: "{{ user }}"
mode: '0644'
- name: Deploy db quadlet
ansible.builtin.template:
src: ott-db.container.j2
dest: "{{ user_home }}/.config/containers/systemd/ott-db.container"
owner: "{{ user }}"
group: "{{ user }}"
mode: '0600'
- name: Deploy redis quadlet
ansible.builtin.copy:
src: ott-redis.container
dest: "{{ user_home }}/.config/containers/systemd/ott-redis.container"
owner: "{{ user }}"
group: "{{ user }}"
mode: '0644'
- name: Deploy server quadlet
ansible.builtin.template:
src: ott-server.container.j2
dest: "{{ user_home }}/.config/containers/systemd/ott-server.container"
owner: "{{ user }}"
group: "{{ user }}"
mode: '0600'
- name: Reload user systemd
become: true
become_user: "{{ user }}"
environment:
XDG_RUNTIME_DIR: "/run/user/{{ user_info.uid }}"
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ user_info.uid }}/bus"
ansible.builtin.systemd:
daemon_reload: true
scope: user
- name: Start user manager
ansible.builtin.systemd:
name: "user@{{ user_info.uid }}.service"
state: started
- name: Start ott-server
become: true
become_user: "{{ user }}"
environment:
XDG_RUNTIME_DIR: "/run/user/{{ user_info.uid }}"
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ user_info.uid }}/bus"
ansible.builtin.systemd:
name: ott-server.service
state: started
scope: user
- name: Debug
ansible.builtin.debug:
msg:
- "Service status: systemctl --user --machine {{ user_info.name }}@.host status ott-server"
- "Read logs: sudo journalctl _UID={{ user_info.uid }} -n 200 --no-pager"
- "Shell: machinectl shell {{ user_info.name }}@.host /bin/bash"
tags:
- always
+15
View File
@@ -0,0 +1,15 @@
hostname="localhost:8080"
log = { level="info" }
api_key="{{ ott_api_key }}"
session_secret="{{ ott_api_key }}"
[info_extractor.youtube]
api_key="{{ google_api_key }}"
[add_preview.search]
enabled=false
[users]
enable_registration=false
-29
View File
@@ -1,29 +0,0 @@
# Postfix main configuration
# https://www.postfix.org/postconf.5.html
# --- Identity ---
myhostname = mail.secretbee.buzz
mydomain = secretbee.buzz
myorigin = $mydomain
# --- Network ---
inet_interfaces = all
inet_protocols = ipv4
# --- Local delivery ---
mydestination = $myhostname, localhost.$mydomain, localhost
# --- Relay ---
mynetworks = 127.0.0.0/8
relayhost =
# --- TLS (outbound) ---
smtp_tls_security_level = enforce
smtp_tls_loglevel = 1
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
# --- Mailbox ---
home_mailbox = Maildir/
# --- Limits ---
message_size_limit = 52428800
+57
View File
@@ -0,0 +1,57 @@
- name: Ufw-ingress
hosts: animeistrash
become: true
tasks:
- name: Install ufw
ansible.builtin.apt:
name: ufw
state: present
- name: Logging
community.general.ufw:
logging: "medium"
- name: UFW - Allow SSH
community.general.ufw:
rule: allow
port: "22"
proto: tcp
- name: UFW - Allow wireguard
community.general.ufw:
rule: allow
port: "41194"
proto: udp
- name: UFW - Allow wireguard routing tcp
community.general.ufw:
rule: allow
interface_in: wg0
route: true
proto: tcp
to_port: '{{ item }}'
loop:
- "25" # mail
- "465" # mail
- "587" # mail
- "993" # mail
- "2222" # gitbee ssh
- "8448" # matrix federation
- "4444" # backup ssh
- "80"
- "443"
- name: UFW - Allow wireguard outgoing
community.general.ufw:
route: true
rule: allow
interface_out: wg0
- name: UFW - Enable and deny by default
community.general.ufw:
state: enabled
default: deny
- name: UFW - Reload firewall
changed_when: true
ansible.builtin.command: ufw reload
+135
View File
@@ -0,0 +1,135 @@
- name: Ufw
hosts: beepi
become: true
tasks:
- name: Install ufw
ansible.builtin.apt:
name: ufw
state: present
- name: Logging
community.general.ufw:
logging: "medium"
- name: UFW - Allow SSH
community.general.ufw:
rule: allow
port: "22"
proto: tcp
- name: UFW - Allow backup SSH
community.general.ufw:
rule: allow
port: "4444"
proto: tcp
- name: UFW - Allow tcp in
community.general.ufw:
rule: allow
port: '{{ item }}'
proto: tcp
loop:
- "139" # samba
- "445" # samba
- "80"
- "443"
- "2222"
- name: UFW - Allow udp in
community.general.ufw:
rule: allow
port: '{{ item }}'
proto: udp
loop:
- "137" # samba
- "138" # samba
- name: UFW - Allow wireguard ingress tcp
community.general.ufw:
rule: allow
interface_in: wg0
proto: tcp
to_port: '{{ item }}'
loop:
- "80"
- "443"
- "4444" # backup ssh
- "8448" # matrix federation
- name: UFW - Allow wireguard routing tcp
community.general.ufw:
rule: allow
interface_in: wg0
route: true
proto: tcp
to_port: '{{ item }}'
loop:
- "25" # mail
- "465" # mail
- "587" # mail
- "993" # mail
- "2222" # gitbee ssh
- "8448" # matrix federation
- name: UFW - Allow podman forwarding
community.general.ufw:
rule: allow
interface_in: podman+
interface_out: podman+
route: true
- name: UFW - Enable DNS from podman
community.general.ufw:
rule: allow
interface_in: podman+
proto: "udp"
to_port: 53
- name: UFW - Allow wireguard outgoing
community.general.ufw:
rule: allow
interface_out: wg0
- name: UFW - Allow wireguard forwarding
community.general.ufw:
rule: allow
interface_in: wg0
interface_out: wg0
route: true
- name: UFW - Allow local network to podman
community.general.ufw:
rule: allow
interface_in: eth0
interface_out: podman+
route: true
- name: UFW - Allow podman to local network
community.general.ufw:
rule: allow
interface_in: podman+
interface_out: eth0
route: true
- name: UFW - Allow node exporter scraping
community.general.ufw:
rule: allow
interface_in: podman+
proto: "tcp"
to_port: 9100
- name: UFW - Allow podman exporter scraping
community.general.ufw:
rule: allow
interface_in: podman+
proto: "tcp"
to_port: 9882
- name: UFW - Enable and deny by default
community.general.ufw:
state: enabled
default: deny
- name: UFW - Reload firewall
changed_when: true
ansible.builtin.command: ufw reload
+36
View File
@@ -0,0 +1,36 @@
[Interface]
PrivateKey = {{ wireguard_server_private_key }}
Address = 10.10.1.1/24
ListenPort = 41194
PostUp = sysctl -w net.ipv4.ip_forward=1
PreUp = iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 25 -j DNAT --to-destination 10.10.1.2:25
PostDown = iptables -t nat -D PREROUTING -i eth0 -p tcp --dport 25 -j DNAT --to-destination 10.10.1.2:25
PreUp = iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 993 -j DNAT --to-destination 10.10.1.2:993
PostDown = iptables -t nat -D PREROUTING -i eth0 -p tcp --dport 993 -j DNAT --to-destination 10.10.1.2:993
PreUp = iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 587 -j DNAT --to-destination 10.10.1.2:587
PostDown = iptables -t nat -D PREROUTING -i eth0 -p tcp --dport 587 -j DNAT --to-destination 10.10.1.2:587
PreUp = iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 465 -j DNAT --to-destination 10.10.1.2:465
PostDown = iptables -t nat -D PREROUTING -i eth0 -p tcp --dport 465 -j DNAT --to-destination 10.10.1.2:465
PreUp = iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 10.10.1.2:80
PostDown = iptables -t nat -D PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 10.10.1.2:80
PreUp = iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j DNAT --to-destination 10.10.1.2:443
PostDown = iptables -t nat -D PREROUTING -i eth0 -p tcp --dport 443 -j DNAT --to-destination 10.10.1.2:443
PreUp = iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8448 -j DNAT --to-destination 10.10.1.2:8448
PostDown = iptables -t nat -D PREROUTING -i eth0 -p tcp --dport 8448 -j DNAT --to-destination 10.10.1.2:8448
PreUp = iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 4444 -j DNAT --to-destination 10.10.1.2:4444
PostDown = iptables -t nat -D PREROUTING -i eth0 -p tcp --dport 4444 -j DNAT --to-destination 10.10.1.2:4444
#PreUp = iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE
#PostDown = iptables -t nat -D POSTROUTING -o wg0 -j MASQUERADE
[Peer]
PublicKey = oI69uWkbkwtpuIYxDNGmzg4nRjY1BIZFVFjZwguIvwE=
AllowedIPs = 10.10.1.2/32
@@ -0,0 +1,32 @@
- name: Wireguard-ingress
hosts: animeistrash
become: true
vars:
wireguard_server_private_key: !vault |
$ANSIBLE_VAULT;1.1;AES256
34313837363964633333373936636462666138386538653939663435376666626230393564366630
6637333264303638383938326132336130343833393466370a623633623163303762616333663135
61666433393939303938623735666439663361633638613466393361626439326465303966303266
3239666637326337650a636433616264386162326535306461326233323961643664373134363634
35633238393933386231373535353635646462383763613362363761363935363965383836366431
3766343166643632306162343761613030653631353361373936
tasks:
- name: Install wireguard
ansible.builtin.apt:
name: wireguard
state: present
- name: Down wg0
changed_when: true
failed_when: false
ansible.builtin.command: wg-quick down wg0
- name: Copy wg0.conf
ansible.builtin.template:
src: wg0.conf.j2
dest: /etc/wireguard/wg0.conf
mode: '0600'
- name: Up wg0
changed_when: true
ansible.builtin.command: wg-quick up wg0
+20
View File
@@ -0,0 +1,20 @@
[Interface]
PrivateKey = {{ wireguard_private_key }}
Address = 10.10.1.2/24
Table = 123
PreUp = ip rule add fwmark 1 table 123 priority 455
PreUp = ip rule add from 10.10.1.2 table 123 priority 456
PostUp = iptables -t mangle -A PREROUTING -i %i -m conntrack --ctstate NEW -j CONNMARK --set-mark 1
PostUp = iptables -t mangle -A PREROUTING -m conntrack --ctdir REPLY -j CONNMARK --restore-mark
PreDown = iptables -t mangle -D PREROUTING -i %i -m conntrack --ctstate NEW -j CONNMARK --set-mark 1
PreDown = iptables -t mangle -D PREROUTING -m conntrack --ctdir REPLY -j CONNMARK --restore-mark
PostDown = ip rule del fwmark 1 table 123 priority 455
PostDown = ip rule del from 10.10.1.2 table 123 priority 456
[Peer]
PublicKey = r0XaxIE3AVud9Z42UPZF3mwoh2R0B0M1EUDY9cvuyDA=
Endpoint = 192.3.44.243:41194
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
+38
View File
@@ -0,0 +1,38 @@
- name: Wireguard
hosts: beepi
become: true
vars:
wireguard_private_key: !vault |
$ANSIBLE_VAULT;1.1;AES256
64663235376666616263333732653733633362393634663130356638353431633635373437323961
3030636636626339316366326161623236303937623338380a656639636338643937323037366139
64633263646664303962323830663435343531393231393939663633343165383163626466633231
3138326563386233390a386237633630656436663062633264366562616632633035343733323331
64366538386364623938663836336661313632376131336338643432646338303738616438623361
6237653737666662336665326237623331383132653431343466
tasks:
- name: Install wireguard
ansible.builtin.apt:
name: wireguard
state: present
- name: Down wg0
changed_when: true
failed_when: false
ansible.builtin.command: wg-quick down wg0
- name: Copy wg0.conf
ansible.builtin.template:
src: wg0.conf.j2
dest: /etc/wireguard/wg0.conf
mode: '0600'
- name: Up wg0
changed_when: true
ansible.builtin.command: wg-quick up wg0
# - name: Start service
# ansible.builtin.service:
# name: wg-quick@wg0
# state: restarted
# enabled: true
Executable
+69
View File
@@ -0,0 +1,69 @@
#!/usr/bin/env python3
import hmac
import hashlib
import base64
import argparse
SMTP_REGIONS = [
"us-east-2", # US East (Ohio)
"us-east-1", # US East (N. Virginia)
"us-west-2", # US West (Oregon)
"ap-south-1", # Asia Pacific (Mumbai)
"ap-northeast-2", # Asia Pacific (Seoul)
"ap-southeast-1", # Asia Pacific (Singapore)
"ap-southeast-2", # Asia Pacific (Sydney)
"ap-northeast-1", # Asia Pacific (Tokyo)
"ca-central-1", # Canada (Central)
"eu-central-1", # Europe (Frankfurt)
"eu-west-1", # Europe (Ireland)
"eu-west-2", # Europe (London)
"eu-south-1", # Europe (Milan)
"eu-north-1", # Europe (Stockholm)
"sa-east-1", # South America (Sao Paulo)
"us-gov-west-1", # AWS GovCloud (US)
"us-gov-east-1", # AWS GovCloud (US)
]
# These values are required to calculate the signature. Do not change them.
DATE = "11111111"
SERVICE = "ses"
MESSAGE = "SendRawEmail"
TERMINAL = "aws4_request"
VERSION = 0x04
def sign(key, msg):
return hmac.new(key, msg.encode("utf-8"), hashlib.sha256).digest()
def calculate_key(secret_access_key, region):
if region not in SMTP_REGIONS:
raise ValueError(f"The {region} Region doesn't have an SMTP endpoint.")
signature = sign(("AWS4" + secret_access_key).encode("utf-8"), DATE)
signature = sign(signature, region)
signature = sign(signature, SERVICE)
signature = sign(signature, TERMINAL)
signature = sign(signature, MESSAGE)
signature_and_version = bytes([VERSION]) + signature
smtp_password = base64.b64encode(signature_and_version)
return smtp_password.decode("utf-8")
def main():
parser = argparse.ArgumentParser(
description="Convert a Secret Access Key to an SMTP password."
)
parser.add_argument("secret", help="The Secret Access Key to convert.")
parser.add_argument(
"region",
help="The AWS Region where the SMTP password will be used.",
choices=SMTP_REGIONS,
)
args = parser.parse_args()
print(calculate_key(args.secret, args.region))
if __name__ == "__main__":
main()
+2
View File
@@ -0,0 +1,2 @@
collections:
- name: community.general