Site Tools


Hotfix release available: 2024-02-06a "Kaos". upgrade now! [55.1] (what's this?)
New release available: 2024-02-06 "Kaos". upgrade now! [55] (what's this?)
projectinsanity:server_setup

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
projectinsanity:server_setup [2020/05/19 17:37] – [wordpress] 10.25.0.1projectinsanity:server_setup [2022/08/12 20:20] (current) – [host.pi] 10.25.0.100
Line 1: Line 1:
 +====== host.pi ======
 +===== Specs =====
 + 1 x Dedicated Root Server SB32 (hetzner)
 +     * Intel Core i7-3770
 +     * 2x HDD SATA 3,0 TB Enterprise
 +     * 4x RAM 8192 MB DDR3
 +     * Location: FSN1
 +===== Payment =====
 +Serverkosten pro Montat: 26,89€ + 5,11€ Steuer: 32,00€
 +^                            ^ Arne         ^ Jonas          ^ ST           ^ Krischi     ^ Schitzu  ^
 +| Juni 18                    | 6,40/6,40    | 6,40/6,40      | 6,40/6,40    | 6,40/6,40   | 6,40/6,40   |
 +| Juli 18                    | 6,40/6,40    | 6,40/6,40      | 6,40/6,40    | 6,40/6,40   | 6,40/6,40   |
 +| August 18                  | 6,40/6,40    | 6,40/6,40      | 6,40/6,40    | 6,40/6,40   | 6,40/6,40   |
 +| September 18               | 6,40/6,40    | 6,40/6,40      | 6,40/6,40    | 6,40/6,40   | 6,40/6,40   |
 +| Oktober 18                 | 6,40/6,40    | 6,40/6,40      | 6,40/6,40    | 6,40/6,40   | 6,40/6,40   |
 +| November 18                | 6,40/6,40    | 6,40/6,40      | 6,40/6,40    | 6,40/6,40   | 6,40/6,40   |
 +| Dezember 18                | 6,40/6,40    | 6,40/6,40      | 6,40/6,40    | 6,40/6,40   | 6,40/6,40   |
 +| Januar 19                  | 0/6,40       | 6,40/6,40      | 6,40/6,40    | 6,40/6,40   | 0/6,40   |
 +| Juli 21 (vorausgezahlt)    | 0/6,40       | 6,40/6,40      | 6,40/6,40    | 0/6,40      | 0/6,40   |
 +Zu überweisen an Jonas
 +===== Überblick =====
 +^ Name        ^ IP           ^ IPv6                  ^ Space      ^ Last backup         ^  
 +| host        | 10.25.0.1    | 2a01:4f8:191:327::  | 5.5TB      | pending (picloud)   |
 +| http        | 10.25.0.100  | 2a01:4f8:191:327::10  | 1TB        | 10.03.21 (picloud)   |
 +| http-pub    | 10.25.0.101  | 2a01:4f8:191:327::11  | 500G       | 24.03.21 (picloud)  |
 +| mail        | 10.25.0.102  | 2a01:4f8:191:327::12  | 500G       | 27.01.21 (picloud)  |
 +| mysql       | 10.25.0.103  | 2a01:4f8:191:327::13  | 100G       | 28.01.21 (picloud)  |
 +| playground  | 10.25.0.104  | 2a01:4f8:191:327::14  | 500G       | 29.03.21 (picloud)  |
 +| storage     | 10.25.0.105  | 2a01:4f8:191:327::15  | 1TB        | 28.04.21 (picloud)   |
 +===== Setup =====
 +  * IPv4: 144.76.16.40
 +  * IPv6: 2a01:4f8:191:327::2
 +Im Rescue system:
 +<code bash>
 +installimage -a -n project-insanity -b grub -r yes -l 0 -i root/.oldroot/nfs/images/archlinux-latest-64-minimal.tar.gz -p /boot:ext4:2G,lvm:vg0:all -v vg0:swap:swap:swap:3G,vg0:root:/:btrfs:40G -f yes -s en
 +</code>
 +==== systemd-networkd ====
 +on the installed host machine, had to change ''2a01:4f8:191:327::2/64'' to ''2a01:4f8:191:327::2/128''. Also ''Address=144.76.16.40'' to ''Address=144.76.16.40/32'':
 +<file - /etc/systemd/networkd/10-enp3s0.network>
 +### Hetzner Online GmbH installimage
 +[Match]
 +Name=enp3s0
 +
 +[Network]
 +Address=2a01:4f8:191:327::2/128
 +Gateway=144.76.16.33
 +Gateway=fe80::1
 +
 +[Address]
 +Address=144.76.16.40/32
 +Peer=144.76.16.33/32
 +IPForward=ipv4
 +</file>
 +<file - /etc/systemd/networkd/25-bridge.netdev>
 +[NetDev]
 +Name=br-internal
 +Kind=bridge
 +</file>
 +<file - /etc/systemd/networkd/25-bridge.network>
 +[Match]
 +Name=br-internal
 +
 +[Network]
 +Address=2a01:4f8:191:327::2/64
 +Address=10.25.0.1/24
 +ConfigureWithoutCarrier=true
 +</file>
 +==== core system ====
 +<code bash>
 +pacman -S mosh tmux htop dmidecode fail2ban openvpn qemu openbsd-netcat openssh easy-rsa fish pacman-contrib
 +chsh -s $(which fish)
 +wget https://arch.jensgutermuth.de/iso/2018.06.01/archlinux-2018.06.01-x86_64.iso -P /var/lib/libvirt/images/
 +chown qemu:qemu /var/lib/libvirt/images/archlinux-2018.06.01-x86_64.iso
 +useradd -m onny -s /bin/fish
 +passwd onny
 +gpasswd -a onny sudo
 +gpasswd -a onny libvirt
 +sudo -u onny mkdir /home/onny/.ssh
 +sudo -u onny vim /home/onny/.ssh/authorized_keys
 +sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/g' /etc/ssh/sshd_config
 +sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config
 +systemctl enable --now sshd fail2ban systemd-networkd systemd-resolved
 +</code>
 +dnsmasq settings, ready to listen on wireguard subnet
 +<file - /etc/dnsmasq.conf>
 +[...]
 +listen-address=127.0.0.1,10.25.0.1,10.25.40.1
 +
 +no-resolv
 +
 +# Google's nameservers, for example
 +server=8.8.8.8
 +server=8.8.4.4
 +</file>
 +systemd resolved dns resolver settings
 +<file - /etc/systemd/resolved.conf>
 +[...]
 +[resolve]
 +DNSStubListener=no
 +</file>
 +<file - /etc/systemd/resolved.conf.d/dns_over_tls.conf>
 +[Resolve]
 +DNSOverTLS=opportunistic
 +</file>
 +<file - /etc/systemd/resolved.conf.d/dnssec.conf>
 +[Resolve]
 +DNSSEC=true
 +</file>
 +<file - /etc/systemd/resolved.conf.d/dns_servers.conf>
 +[Resolve]
 +DNS=2620:fe::fe 9.9.9.9
 +</file>
 +<file - /etc/hosts>
 +[...]
 +10.25.0.1 host.pi
 +10.25.0.100 http.pi
 +10.25.0.101 http-pub.pi
 +10.25.0.102 mail.pi
 +10.25.0.103 mysql.pi
 +10.25.0.104 playground.pi
 +10.25.0.105 storage.pi
 +
 +2a01:4f8:191:327::2 host.pi
 +2a01:4f8:191:327::10 http.pi
 +2a01:4f8:191:327::11 http-pub.pi
 +2a01:4f8:191:327::12 mail.pi
 +2a01:4f8:191:327::13 mysql.pi
 +2a01:4f8:191:327::14 playground.pi
 +2a01:4f8:191:327::15 storage.pi
 +
 +#vpn clients
 +10.25.0.200      onny           onny.pi
 +10.25.0.201      st             st.pi
 +10.25.0.202      neutrino       neutrino.pi
 +10.25.0.203      arne           arne.pi
 +
 +2a01:4f8:191:327::100 onny onny.pi
 +2a01:4f8:191:327::101 st st.pi
 +2a01:4f8:191:327::102 neutrino neutrino.pi
 +2a01:4f8:191:327::103 arne arne.pi
 +</file>
 +custom pi archlinux repo
 +<file - /etc/pacman.conf>
 +...
 +[projectinsanity]
 +SigLevel = PackageOptional
 +Server = https://onny.project-insanity.org/archlinux
 +</file>
 +archlinux auto update
 +<file - /etc/pacman.conf>
 +...
 +[projectinsanity]
 +SigLevel = PackageOptional
 +Server = https://onny.project-insanity.org/archlinux
 +</file>
 +<file - /etc/systemd/system/autoupdate.service>[Unit]
 +Description=Automatic Update
 +After=network-online.target 
 +
 +[Service]
 +Type=simple
 +ExecStart=/usr/bin/sh -c "/usr/bin/pacman -Syuq --noconfirm --needed --noprogressbar && rm /var/cache/pacman/pkg/*.zst"
 +TimeoutStopSec=180
 +KillMode=process
 +KillSignal=SIGINT
 +
 +[Install]
 +WantedBy=multi-user.target
 +</file>
 +<file - /etc/systemd/system/autoupdate.timer>
 +[Unit]
 + Description=Automatic Update when booted up after 5 minutes then check the system for updates every 60 minutes
 +
 +[Timer]
 + OnBootSec=5min
 + OnUnitActiveSec=60min
 + Unit=autoupdate.service
 +
 +[Install]
 + WantedBy=multi-user.target
 +</file>
 +<code bash>
 +systemctl enable --now autoupdate.timer
 +</code>
 +automatic timed reboot after kernel upgrade
 +<file - /etc/pacman.d/hooks/linux.hook>
 +[Trigger]
 +Operation = Install
 +Operation = Upgrade
 +Type = Package
 +Target = linux
 +
 +[Action]
 +Description = Enable timer for reboot after kernel upgrade
 +When = PostTransaction
 +Exec = /usr/bin/systemctl start kernel-upgrade.timer
 +</file>
 +<file - /etc/systemd/system/kernel-upgrade.timer>
 +[Unit]
 +Description=Reboot in the morning after kernel upgrade
 +
 +[Timer]
 +OnCalendar=*-*-* 06:00:00
 +Unit=kernel-upgrade.service
 +
 +[Install]
 +WantedBy=multi-user.target
 +</file>
 +<file - /etc/systemd/system/kernel-upgrade.service>
 +[Unit]
 +Description=Reboot after kernel upgrade
 +
 +[Service]
 +Type=simple
 +ExecStart=/usr/bin/systemctl reboot
 +
 +[Install]
 +WantedBy=multi-user.target
 +</file>
 +==== nftables ====
 +nftables firewall & routing
 +<file - /etc/nftables.conf>
 +define TCP_PORT_QUAKEJS_DS = 27960
 +define TCP_PORT_IMAPS = 993
 +define TCP_PORT_SMTPS = 587
 +define TCP_PORT_SMTP = 25
 +define TCP_PORT_SSH = 22
 +define TCP_PORT_HTTP = 80
 +define TCP_PORT_HTTPS = 443
 +define UDP_PORT_WIREGUARD = 51820
 +define UDP_PORT_MOSH = 60000-61000
 +define HOST_HTTP_PI = 10.25.0.100
 +define HOST_MAIL_PI = 10.25.0.102
 +define HOST_PLAYGROUND_PI = 10.25.0.104
 +
 +table inet filter {
 + set tcp_accepted {
 + type inet_service
 + flags interval
 + elements = { $TCP_PORT_SSH, $TCP_PORT_HTTP, $TCP_PORT_HTTPS, $TCP_PORT_SMTPS, $TCP_PORT_IMAPS, $TCP_PORT_SMTP, $TCP_PORT_QUAKEJS_DS }
 + }
 +
 + set udp_accepted {
 + type inet_service
 + flags interval
 + elements = { $UDP_PORT_WIREGUARD, $UDP_PORT_MOSH }
 + }
 +
 + chain base_checks {
 + ct state { established, related } accept
 + ct state invalid drop
 + }
 +
 + chain input {
 + type filter hook input priority filter; policy drop;
 + jump base_checks
 + iifname "lo" accept
 + ip protocol icmp icmp type { echo-reply, destination-unreachable, echo-request, time-exceeded, parameter-problem } accept
 + ip6 nexthdr ipv6-icmp icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request, echo-reply, mld-listener-query, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept
 + tcp dport @tcp_accepted accept
 + udp dport @udp_accepted accept
 + ip saddr 10.25.0.1/24 accept
 + ip saddr 10.25.40.1/24 accept
 + reject
 + }
 +
 + chain forward {
 + type filter hook forward priority filter; policy drop;
 + jump base_checks
 + ip daddr 10.25.0.100 ct status dnat accept
 + ip saddr {10.25.0.1/24,10.25.40.1/24} accept
 + ip daddr {10.25.0.1/24,10.25.40.1/24} accept
 +         oif br-internal accept
 +         iif br-internal accept
 + }
 +
 + chain output {
 + type filter hook output priority filter; policy accept;
 + }
 +}
 +table ip nat {
 + chain prerouting {
 + type nat hook prerouting priority filter; policy accept;
 +
 + iif "enp3s0" tcp dport { $TCP_PORT_HTTP, $TCP_PORT_HTTPS } dnat to $HOST_HTTP_PI
 +
 + # Forward web traffic to http.pi
 + ip daddr { 10.25.0.1/24,144.76.16.40 } tcp dport { $TCP_PORT_HTTP,$TCP_PORT_HTTPS } dnat to $HOST_HTTP_PI
 +
 + # Forward mail traffic to mail.pi
 + iif "enp3s0" tcp dport { $TCP_PORT_SMTP, $TCP_PORT_SMTPS, $TCP_PORT_IMAPS } dnat to $HOST_MAIL_PI
 +
 + iif "enp3s0" tcp dport { $TCP_PORT_QUAKEJS_DS } dnat to $HOST_PLAYGROUND_PI
 + }
 +
 + chain postrouting {
 + type nat hook postrouting priority srcnat; policy accept;
 + ip saddr 10.25.0.0/24 oif {"enp3s0", "br-internal"} snat 144.76.16.40
 + }
 +}
 +</file>
 +<file - nftables.service.d/overwrite.conf>
 +[Unit]
 +Wants=
 +Wants=libvirtd.service
 +Before=
 +After=libvirtd.service
 +
 +[Service]
 +Type=simple
 +Restart=always
 +RestartSec=5
 +</file>
 +<code bash>
 +pacman -S nftables
 +systemctl enable --now nftables
 +</code>
 +==== libvirtd ====
 +libvirt network configuration file
 +<file - /tmp/net-internal.xml>
 +network connections='6'>
 +  <name>internal</name>
 +  <uuid>0a2dff47-afc7-4d27-91b0-5f61a1f5cbaa</uuid>
 +  <forward mode='bridge'/>
 +  <bridge name='br-internal'/>
 +</network>
 +</file>
 +libvirt qemu hook
 +<code bash>
 +pacman -S libvirt virt-install dnsmasq glusterfs
 +virsh pool-define-as --name 'vg0' --type 'logical' --source-format 'lvm2' --target '/dev/vg0'
 +virsh pool-autostart vg0
 +virsh pool-start vg0
 +virsh net-define /tmp/net-internal.xml
 +virsh net-start internal
 +virsh net-autostart internal
 +systemctl enable --now libvirtd
 +</code>
 +
 +==== wireguard ====
 +<code bash>
 +pacman -S wireguard-tools
 +cd /etc/wireguard
 +wg genkey | tee privatekey | wg pubkey > publickey
 +chmod 600 privatekey
 +chown root:root privatekey
 +</code>
 +<file - /etc/systemd/network/99-server.netdev>
 +[NetDev]
 +Name = wg0
 +Kind = wireguard
 +Description = Wireguard
 +
 +[WireGuard]
 +ListenPort = 51820
 +PrivateKey = [PI_SERVER_PRIVKEY]
 +
 +[WireGuardPeer]
 +# onny
 +PublicKey = [ONNY_PUBKEY]
 +AllowedIPs = 10.25.40.2/32
 +
 +[WireGuardPeer]
 +# st
 +PublicKey = [ST_PUBKEY]
 +AllowedIPs = 10.25.40.3/32
 +
 +[WireGuardPeer]
 +# neutrino
 +PublicKey = [NEUTRINO_PUBKEY]
 +AllowedIPs = 10.25.40.4/32
 +
 +[WireGuardPeer]
 +# jolla (neutrino)
 +PublicKey = [JOLLA_PUBKEY]
 +AllowedIPs = 10.25.40.5/32
 +
 +[WireGuardPeer]
 +# picloud (onny)
 +PublicKey = [PICLOUD_PUBKEY]
 +AllowedIPs = 10.25.40.6/32
 +</file>
 +<file - /etc/systemd/network/99-server.network>
 +[Match]
 +Name = wg0
 +
 +[Network]
 +Address = 10.25.40.1/24
 +DNS=10.25.0.1
 +DNSSEC=false
 +IPForward=ipv4
 +</file>
 +=== client ===
 +<code bash>
 +pacman -S wireguard-tools
 +cd /etc/wireguard
 +wg genkey | tee privatekey | wg pubkey > publickey
 +chmod 600 privatekey
 +chown root:root privatekey
 +</code>
 +<file - /etc/systemd/network/99-client.netdev>
 +[NetDev]
 +Name = wg0
 +Kind = wireguard
 +Description = Wireguard
 +
 +[WireGuard]
 +PrivateKey = [ONNY's PRIVATE KEY]
 +
 +[WireGuardPeer]
 +PublicKey = [SERVER PUBLICKEY]
 +AllowedIPs = 10.25.0.0/16
 +Endpoint = 2a01:4f8:191:327::2:51820
 +Endpoint = 144.76.16.40:51820
 +PersistentKeepalive = 25
 +</file>
 +<file - /etc/systemd/network/99-client.network>
 +[Match]
 +Name = wg0
 +
 +[Network]
 +Address = 10.25.40.2/16
 +</file>
 +<code bash>
 +systemctl restart systemd-networkd
 +</code>
 +==== systemd-journal logging server ====
 +<file - /etc/systemd/journal-remote.conf>
 +[Remote]
 +SplitMode=host
 +</file>
 +<file - /etc/systemd/system/systemd-journal-remote.service>
 +[Unit]
 +Description=Journal Remote Sink Service
 +Documentation=man:systemd-journal-remote(8) man:journal-remote.conf(5)
 +Requires=systemd-journal-remote.socket
 +
 +[Service]
 +ExecStart=/lib/systemd/systemd-journal-remote --listen-http=-3 --output=/var/log/journal/remote/
 +User=systemd-journal-remote
 +Group=systemd-journal-remote
 +PrivateTmp=yes
 +PrivateDevices=yes
 +PrivateNetwork=yes
 +WatchdogSec=3min
 +
 +[Install]
 +Also=systemd-journal-remote.socket
 +</file>
 +<code bash>
 +mkdir -p /var/log/journal/remote
 +chown -R systemd-journal-remote:systemd-journal-remote /var/log/journal/remote
 +pacman -S libmicrohttpd
 +ufw allow from 10.25.0.0/24 to any proto tcp port 19532
 +systemctl enable --now systemd-journal-remote
 +</code>
 +===== ArchLinux Gastsystem =====
 +==== Erstellen ====
 +<code bash>
 +virt-install --video qxl --channel spicevmc --graphics spice,listen=127.0.0.1 --name=http --vcpus 4 --memory 8048 --disk pool=vg0,size=1000,bus=virtio --cdrom /var/lib/libvirt/images/archlinux-2018.06.01-x86_64.iso --network network:internal,model=virtio --virt-type kvm --autostart --noautoconsole
 +</code>
 +==== Löschen ====
 +<code bash>
 +virsh destroy http
 +virsh undefine http
 +lvremove /dev/vg0/http
 +</code>
 +==== Speicher vergrößern ====
 +<code bash>virsh shutdown http
 +lvresize -L +20G vg0/http
 +virsh start http</code>
 +Auf dem Gastsystem ausführen:
 +<code bash>sgdisk -og -a 1024 -n 1:1024:2047 -c 1:"BIOS Boot Partition" -t 1:ef02 /dev/vda
 +sgdisk -n2:2048:0 -c2:"ArchRoot" -p /dev/vda
 +shutdown -h now # then start again after that
 +btrfs filesystem resize max /</code>
 +Bei neueren Version von libguestfs-tools (>1.16.34) könnte man auch die Partitionstabelle und Dateisystem [[http://blog.oneiroi.co.uk/linux/kvm/virt-resize/RHEL/LVM/kvm-linux-expanding-a-lvm-guest-file-system-using-virt-resize/|von dem Host aus resizen]] und müsste dafür nicht das Gastsystem neustarten.
 +
 +==== Backup ====
 +Raw backup logical volume to picloud (homeserver onnuex)
 +<code bash>
 +lvcreate -s -n playground_snap -L 20G /dev/vg0/playground
 +dd if=/dev/vg0/playground.img_snap bs=4096 | pv | gpg --batch --passphrase "my_secret_password" --symmetric --compress-algo zlib | ssh picloud@picloud.sexypump.de 'dd of=/mnt/backups/project-insanity/playground_$(date +"%Y-%m-%d").img.gpg bs=4096'
 +lvremove /dev/vg0/playground_snap
 +</code>
 +Recover backup
 +<code bash>
 +gpg -o /mnt/playground.img -d /mnt/playground.img.gpg
 +</code>
 +Unfinished backup script:
 +<code bash>
 +sas="$1"
 +password="$2"
 +
 +for vol in `lvs | cut -f3 -d " " | tail -n+2`
 + do echo "Backing up $vol"
 + lvcreate -s -n "${vol}_snap" -L 20G "/dev/vg0/${vol}"
 + pv -cN source "/dev/vg0/${vol}_snap" | gpg --batch --passphrase "${password}" --symmetric --compress-algo zlib | azcopy cp "https://myaccount.blob.core.windows.net/mycontainer/${vol}_$(date +"%Y-%m-%d").img.gpg?${sas}"
 + lvremove "/dev/vg0/${vol}_snap"
 +done
 +</code>
 +==== Einrichten ====
 +<code bash>
 +mkfs.btrfs /dev/sda
 +ifconfig eth0 10.25.0.120 up
 +route add default gw 10.25.0.1
 +mount /dev/sda /mnt
 +ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
 +pacstrap /mnt base base-devel tmux mosh yajl wipe rsync procps neovim lsof strace htop net-tools pkgfile dnsutils iotop aria2 tcpdump nload grub btrfs-progs gptfdisk ntp wget rxvt-unicode-terminfo pwgen mlocate fail2ban pv expac openssh git devtools fish nftables ripgrep bat fd pacman-contrib
 +genfstab -p /mnt >> /mnt/etc/fstab
 +arch-chroot /mnt
 +chsh -s $(which fish)
 +sed -i 's/^#?SystemMaxUse=.*$/SystemMaxUse=200M/g' /etc/systemd/journald.conf
 +sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/g' /etc/ssh/sshd_config
 +sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config
 +sed -i 's/^#Color/Color/g' /etc/pacman.conf
 +mkdir /etc/pacman.d/hooks
 +ln -s /usr/share/libalpm/hooks/30-systemd-daemon-reload.hook /etc/pacman.d/hooks/
 +echo "http-pub2" >> /etc/hostname
 +ln -sf /usr/share/zoneinfo/UTC /etc/localtime
 +sed -i 's/#en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen
 +locale-gen
 +echo 'LANG="en_US.UTF-8"' > /etc/locale.conf
 +echo "KEYMAP=de" > /etc/vconsole.conf
 +mkinitcpio -p linux
 +sed -i '/GRUB_TIMEOUT/s/5/0/' /etc/default/grub
 +grub-mkconfig -o /boot/grub/grub.cfg
 +grub-install /dev/sda
 +passwd
 +useradd -m onny -s /usr/bin/fish
 +passwd onny
 +usermod -a -G sudo onny
 +sudo -u onny mkdir /home/onny/.ssh
 +sudo -u onny vim /home/onny/.ssh/authorized_keys
 +chown -R onny:onny /home/onny
 +updatedb
 +pkgfile --update
 +echo "UserParameter=archlinuxupdates,if [ -d /tmp/pacmandb ]; then fakeroot pacman -Syup --dbpath /tmp/pacmandb | grep "pkg.tar.xz" -c; else mkdir /tmp/pacmandb && ln -s /var/lib/pacman/local /tmp/pacmandb && fakeroot pacman -Syup --dbpath /tmp/pacmandb | grep "pkg.tar.xz" -c; fi" >> /etc/zabbix/zabbix_agentd.conf
 +sed -i 's/^Server=.*$/Server=http-new.pi/g' /etc/zabbix/zabbix_agentd.conf
 +systemctl enable --now sshd systemd-networkd nftables fail2ban systemd-resolved
 +timedatectl set-ntp true
 +exit
 +reboot
 +</code>
 +=== nftables ===
 +<file - /etc/nftables.conf>
 +table inet filter {
 +        set tcp_accepted {
 +                type inet_service
 +                flags interval
 +                elements = { 22 }
 +        }
 +
 +        set udp_accepted {
 +                type inet_service
 +                flags interval
 +                elements = { 60000-61000 }
 +        }
 +
 +        chain base_checks {
 +                ct state { established, related } accept
 +                ct state invalid drop
 +        }
 +
 +        chain input {
 +                type filter hook input priority filter; policy drop;
 +                jump base_checks
 +                iifname "lo" accept
 +                ip protocol icmp icmp type { echo-reply, destination-unreachable, echo-request, time-exceeded, parameter-problem } accept
 +                ip6 nexthdr ipv6-icmp icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request, echo-reply, mld-listener-query, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept
 +                tcp dport @tcp_accepted accept
 +                udp dport @udp_accepted accept
 +                reject
 +        }
 +
 +        chain forward {
 +                type filter hook forward priority filter; policy drop;
 +                jump base_checks
 +        }
 +
 +        chain output {
 +                type filter hook output priority filter; policy accept;
 +        }
 +}
 +</file>
 +=== systemd-networkd ===
 +<file - /etc/systemd/network/ens3.network>
 +[Match]
 +Name=ens3
 +
 +[Network]
 +Address=2a01:4f8:191:327::10/64
 +Address=10.25.0.100/24
 +Gateway=10.25.0.1
 +Gateway=2a01:4f8:191:327::2
 +DNS=10.25.0.1
 +DNSSEC=false
 +
 +LinkLocalAddressing = no
 +IPv6AcceptRA = no
 +</file>
 +=== pacman ===
 +project-insanity build server repo
 +<file - /etc/pacman.conf>
 +[...]
 +
 +[projectinsanity]
 +SigLevel = PackageOptional
 +Server = https://onny.project-insanity.org/archlinux
 +</file>
 +archlinux auto update
 +<file - /etc/systemd/system/autoupdate.service>
 +[Unit]
 + Description=Automatic Update
 + After=network-online.target 
 +
 +[Service]
 + Type=simple
 + ExecStart=/usr/bin/pacman -Syuq --noconfirm --needed --noprogressbar 
 + TimeoutStopSec=180
 + KillMode=process
 + KillSignal=SIGINT
 +
 +[Install]
 + WantedBy=multi-user.target
 +</file>
 +<file - /etc/systemd/system/autoupdate.timer>
 +[Unit]
 + Description=Automatic Update when booted up after 5 minutes then check the system for updates every 60 minutes
 +
 +[Timer]
 + OnBootSec=5min
 + OnUnitActiveSec=60min
 + Unit=autoupdate.service
 +
 +[Install]
 + WantedBy=multi-user.target
 +</file>
 +<code bash>
 +systemctl enable --now autoupdate.timer
 +</code>
 +=== systemd-journald ===
 +systemd logging upload
 +<file - /etc/systemd/journal-upload.conf>
 +[Upload]
 +URL=http://10.25.0.1:19532
 +</file>
 +<file - /etc/systemd/system/systemd-journal-upload.service>
 +[Unit]
 +Description=Journal Remote Upload Service
 +Documentation=man:systemd-journal-upload(8)
 +After=network.target
 +
 +[Service]
 +ExecStart=/lib/systemd/systemd-journal-upload --save-state
 +User=systemd-journal-upload
 +SupplementaryGroups=systemd-journal
 +PrivateTmp=yes
 +PrivateDevices=yes
 +WatchdogSec=3min
 +
 +# Add reset/restart options
 +TimeoutSec=120
 +Restart=on-failure
 +RestartSec=2
 +
 +# Add accounting options
 +CPUAccounting=true
 +BlockIOAccounting=true
 +MemoryAccounting=false
 +TasksAccounting=true
 +
 +# If there are many splits up journal files we need a lot of file descriptors to access them all and combine
 +LimitNOFILE=16384
 +
 +[Install]
 +WantedBy=multi-user.target
 +</file>
 +<code bash>
 +useradd systemd-journal-upload
 +mkdir /var/lib/systemd/journal-upload
 +chown -R systemd-journal-upload:systemd-journal-upload /var/lib/systemd/journal-upload
 +systemctl enable --now systemd-journal-upload
 +</code>
 +
 +==== Maintainance ====
 +Update configs
 +<code bash>
 +sudo pacdiff
 +</code>
 +====== mail.pi ======
 +on mail.pi
 +<code bash>
 +pacman -S maddy
 +systemctl enable --now maddy
 +nft add rule inet filter input position 17 tcp dport smtps accept
 +nft add rule inet filter input position 17 tcp dport smtp accept
 +nft add rule inet filter input position 17 tcp dport imaps accept
 +nft list ruleset > /etc/nftables.conf
 +</code>on
 +<file - /etc/maddy/maddy.conf>
 +...
 +$(hostname) = turbotux.de
 +...
 +$(primary_domain) = turbotux.de
 +...
 +tls /etc/maddy/certs/$(hostname)/fullchain.pem /etc/maddy/certs/$(hostname)/privkey.pem
 +...
 +</file>
 +<code bash>
 +maddyctl users create postmaster
 +maddyctl users create onny@turbotux.de
 +</code>
 +turbotux.de dns record. get dkim key in ''/var/lib/maddy/dkim-keys/turbotux.de-default.dns''
 +<code>
 +turbotux.de.    A     144.76.16.40
 +turbotux.de.    AAAA  2a01:4f8:191:327::10
 +turbotux.de.    MX    10 turbotux.de
 +turbotux.de.    TXT   "v=spf1 mx -all"
 +_dmarc.turbotux.de.    TXT    "v=DMARC1; p=none; ruf=postmaster@turbotux.de"
 +default._domainkey.turbotux.de    TXT   "v=DKIM1; k=ed25519; p=nAcUUozPlhc4VPhp7hZl+owES7j7OlEv0laaDEDBAqg="
 +</code>
 +forwarding/nat on host.pi
 +<code bash>
 +nft add rule inet filter input position 19 tcp dport smtps accept
 +nft add rule inet filter input position 19 tcp dport smtp accept
 +nft add rule inet filter input position 19 tcp dport imaps accept
 +nft add rule ip nat prerouting position 4 iifname "enp3s0" tcp dport imaps dnat to 10.25.0.102
 +nft add rule ip nat prerouting position 4 iifname "enp3s0" tcp dport smtp dnat to 10.25.0.102
 +nft add rule ip nat prerouting position 4 iifname "enp3s0" tcp dport smtps dnat to 10.25.0.102
 +nft list ruleset > /etc/nftables.conf
 +</code>
 +tls. on mail.pi
 +<code bash>
 +chmod +x /var/lib/private
 +sudo -u maddy ssh-keygen # all default values
 +cat /var/lib/maddy/.ssh/id_rsa.pub
 +</code>
 +on http.pi
 +<code bash>
 +useradd -m maddy
 +mkdir /home/maddy/.ssh
 +vim /home/maddy/.ssh/authorized_keys
 +setfacl -R -d -m u:maddy:rx /var/lib/caddy/acme/acme-v02.api.letsencrypt.org/sites/t
 +urbotux.de/turbotux.de.crt /var/lib/caddy/acme/acme-v02.api.letsencrypt.org/sites/turbotux.de/turbotux
 +.de.key # this does not work so well yet :(
 +</code>
 +====== mysql.pi ======
 +===== mariadb =====
 +<code bash>
 +pacman -S mariadb
 +mysql_install_db --user=mysql --basedir=/usr --datadir=/var/lib/mysql
 +mysqladmin -u root password 'new-password'
 +mysql_secure_installation
 +systemctl enable --now mariadb
 +nft add rule inet filter input position 17 ip saddr 10.25.0.0/24 tcp dport mysql accept
 +nft add rule inet filter input position 17 ip6 saddr 2a01:4f8:191:327::0/64 tcp dport mysql accept
 +nft list ruleset > /etc/nftables.conf
 +</code>
 +<file - /etc/pacman.d/hooks/40-mariadb.hook>
 +# Restart mariadb service
 +
 +[Trigger]
 +Operation = Install
 +Operation = Upgrade
 +Type = Package
 +Target = mariadb
 +
 +[Action]
 +Description = Restarting mariadb service
 +When = PostTransaction
 +Exec = /usr/bin/sh -c "/usr/bin/mysql_upgrade -u root -p'****' && /usr/bin/systemctl restart mariadb"
 +</file>
 +<code bash>
 +chmod 600 /etc/pacman.d/hooks/40-mariadb.hook
 +</code>
 +temporary workaround to get nextcloud to work, see: https://github.com/nextcloud/server/issues/27085
 +<file - /etc/my.cnf.d/server.cnf>
 +[...]
 +[server]
 +
 +innodb_read_only_compressed=0
 +[...]
 +</file>
 +===== postgresql =====
 +<code bash>
 +pacman -S postgresql postgresql-old-upgrade
 +sudo su - postgres -c "initdb -D /var/lib/postgres/data"
 +systemctl enable --now postgresql
 +nft add rule inet filter input position 17 ip saddr 10.25.0.0/24 tcp dport postgresql accept
 +nft add rule inet filter input position 17 ip6 saddr 2a01:4f8:191:327::0/64 tcp dport postgresql accept
 +nft list ruleset > /etc/nftables.conf
 +</code>
 +<file - /var/lib/postgres/data/postgresql.conf>
 +[...]
 +listen_addresses = '*'
 +[...]
 +</file>
 +<file - /var/lib/postgres/data/pg_hba.conf>
 +[...]
 +host    all             all             10.25.0.0/24            md5
 +host    all             all             2a01:4f8:191:327::/64           md5
 +</file>
 +<file - /etc/pacman.d/hooks/postgresql.hook>
 +# Restart postgresql service
 +
 +[Trigger]
 +Operation = Install
 +Operation = Upgrade
 +Type = Package
 +Target = postgresql
 +
 +[Action]
 +Description = Restarting postgresql service
 +When = PostTransaction
 +Exec = /usr/bin/systemctl restart postgresql
 +</file>
 +====== http.pi ======
 +<code bash>
 +pacman -S caddy dokuwiki gitlab php-fpm php-apcu phpmyadmin wordpress nginx
 +systemctl enable --now caddy php-fpm
 +nft add rule inet filter input position 17 tcp dport "{http, https}" accept
 +nft list ruleset > /etc/nftables.conf
 +</code>
 +<file - /etc/pacman.d/hooks/php.hook>
 +# Restart php service
 +
 +[Trigger]
 +Operation = Install
 +Operation = Upgrade
 +Type = Package
 +Target = php
 +Target = php-fpm
 +
 +[Action]
 +Description = Restarting php service
 +When = PostTransaction
 +Exec = /usr/bin/systemctl restart php-fpm
 +</file>
 +custom caddy installation
 +<code bash>
 +pacaur -d caddy
 +</code>
 +<file - ~/.cache/pacaur/caddy/PKGBUILD>
 +[...]
 +#    'http.hugo'
 +    'http.ipfilter'
 +#    'http.jekyll'
 +[...]
 +</file>
 +<code bash>
 +cd ~/.cache/pacaur/caddy
 +makepkg -i --skipinteg
 +</code>
 +<file - /etc/systemd/system/caddy.service.d/override.conf>
 +[Service]
 +ProtectHome=false
 +</file>
 +===== caddy =====
 +<code bash>
 +pacman -S caddy
 +gpasswd -a caddy http
 +</code>
 +<file - /etc/caddy/Caddyfile>
 +import /etc/caddy/conf.d/*
 +</file>
 +<file - /etc/caddy/conf.d/ausstellung-virtuell.de.conf>
 +www.ausstellung-virtuell.de ausstellung-virtuell.de {
 +
 +        log {
 +                output file     /var/log/caddy/ausstellung-virtuell.de.log
 +                format single_field common_log
 +        }
 +
 +    reverse_proxy http://http-pub.pi
 +
 +}
 +</file>
 +<file - /etc/caddy/conf.d/blog.project-insanity.org.conf>
 +blog.project-insanity.org {
 +
 +        root    * /usr/share/webapps/wordpress
 +        file_server
 +        log {
 +                output file     /var/log/caddy/blog.project-insanity.org.log
 +                format single_field common_log
 +        }
 +
 +        php_fastcgi unix//var/run/php-fpm/php-fpm.sock
 +
 +    @uploads {
 +          path_regexp path /uploads\/(.*)\.php
 +        }
 +        rewrite @uploads /
 +
 +        @wp-admin {
 +          path  not ^\/wp-admin/*
 +        }
 +        rewrite @wp-admin {path}/index.php?{query}
 +
 +}
 +
 +</file>
 +<file - /etc/caddy/conf.d/git.project-insanity.org.conf>
 +git.project-insanity.org {
 +
 +        log {
 +                output file     /var/log/caddy/git.project-insanity.org.log
 +                format single_field common_log
 +        }
 +
 +    reverse_proxy unix//run/gitlab/gitlab-workhorse.socket
 +
 +}
 +</file>
 +<file - /etc/caddy/conf.d/jhartung.sinewell.de.conf>
 +jhartung.sinewell.de {
 +
 +        log {
 +                output file     /var/log/caddy/jhartung.sinewell.de.log
 +                format single_field common_log
 +        }
 +
 +    reverse_proxy https://wrsmtwhrearj2wyg.myfritz.net:46190
 +
 +}
 +</file>
 +<file - /etc/caddy/conf.d/nextcloud.project-insanity.org.conf>
 +nextcloud.project-insanity.org {
 +
 +        root    * /usr/share/webapps/nextcloud
 +        file_server
 +        log {
 +                output file     /var/log/caddy/nextcloud.project-insanity.org.log
 +                format single_field common_log
 +        }
 +
 +        php_fastcgi unix//var/run/php-fpm/php-fpm.sock {
 +                env front_controller_active true
 +        }
 +
 +        header {
 +                # enable HSTS
 +                Strict-Transport-Security max-age=31536000;
 +        }
 +
 +        redir /.well-known/carddav /remote.php/dav 301
 +        redir /.well-known/caldav /remote.php/dav 301
 +
 +        # .htaccess / data / config / ... shouldn't be accessible from outside
 +        @forbidden {
 +                path    /.htaccess
 +                path    /data/*
 +                path    /config/*
 +                path    /db_structure
 +                path    /.xml
 +                path    /README
 +                path    /3rdparty/*
 +                path    /lib/*
 +                path    /templates/*
 +                path    /occ
 +                path    /console.php
 +        }
 +
 +        respond @forbidden 404
 +
 +}
 +</file>
 +<file - /etc/caddy/conf.d/onny.project-insanity.org.conf>
 +onny.project-insanity.org {
 +
 +        log {
 +                output file     /var/log/caddy/onny.project-insanity.org.log
 +                format single_field common_log
 +        }
 +
 +    reverse_proxy http://http-pub.pi
 +
 +}
 +</file>
 +<file - /etc/caddy/conf.d/wiki.project-insanity.org.conf>
 +wiki.project-insanity.org {
 +
 +        root    * /usr/share/webapps/dokuwiki
 +        file_server
 +        log {
 +                output file     /var/log/caddy/wiki.project-insanity.org.log
 +                format single_field common_log
 +        }
 +
 +    encode zstd gzip
 +        php_fastcgi unix//var/run/php-fpm/php-fpm.sock
 +
 +    @restrict_files {
 +      path /data/* /conf/* /bin/* /inc/* /vendor/* /install.php
 +    }
 +    respond @restrict_files 404
 +
 +        @allow_media {
 +          path_regexp path ^/_media/(.*)$
 +        }
 +        rewrite @allow_media /lib/exe/fetch.php?media=/{http.regexp.path.1}
 +
 +    @allow_detail   {
 +      path /_detail*
 +    }
 +    rewrite @allow_detail /lib/exe/detail.php?media={path}
 +
 +    @allow_export   {
 +      path /_export*
 +      path_regexp export /([^/]+)/(.*)
 +    }
 +    rewrite @allow_export /doku.php?do=export_{http.regexp.export.1}&id={http.regexp.export.2}
 +
 +    try_files {path} {path}/ /doku.php?id={path}&{query}
 +}
 +</file>
 +<file - /etc/caddy/conf.d/http.pi.conf>
 +http://http.pi {
 +
 +        root    * /var/www
 +        file_server * browse
 +        log {
 +                output file     /var/log/caddy/http.pi.log
 +                format single_field common_log
 +        }
 +
 +        php_fastcgi unix//var/run/php-fpm/http.pi_php-fpm.sock
 +}
 +</file>
 +<file - /etc/caddy/conf.d/saai.digital>
 +beta.saai.digital {
 +
 +        log {
 +                output file     /var/log/caddy/saai.digital.log
 +                format single_field common_log
 +        }
 +
 +    reverse_proxy http://playground.pi:8080
 +
 +}
 +</file>
 +<file - /etc/caddy/conf.d/office.project-insanity.org.conf>
 +office.project-insanity.org {
 +
 +        log {
 +                output file     /var/log/caddy/office.project-insanity.org.log
 +                format single_field common_log
 +        }
 +
 +    # Routing Onlyoffice Spellchecker
 +    route /spellchecker/* {
 +        uri strip_prefix /spellchecker
 +        reverse_proxy localhost:8081
 +    }
 +
 +    # Routing Onlyoffice Documentserver etc.
 +        @onlyoffice {
 +          path_regexp path ^/(cache|downloadas|sdkjs|plugins.json|fonts|web-apps|upload|doc|healthcheck|coauthoring|ConvertService.ashx)
 +        }
 +        rewrite @onlyoffice /proxy/{uri}
 +    route /proxy/* {
 +        uri strip_prefix /proxy/
 +        reverse_proxy localhost:8000
 +    }
 +
 +    # Route to Officepad
 +    reverse_proxy / http://localhost:8082
 +
 +}
 +</file>
 +need to convert
 +<file - /etc/caddy/conf.d/turbotux.de.conf>
 +www.turbotux.de turbotux.de {
 +    log /var/log/caddy/turbotux.de_access.log
 +    errors /var/log/caddy/turbotux.de_errors.log
 +    gzip
 +    tls onny@project-insanity.org
 +    proxy / http://picloud.sexypump.de:8096 {
 +        websocket
 +    }
 +}
 +</file>
 +===== php-fpm =====
 +<code bash>
 +cp /etc/php/php-fpm.d/www.conf /etc/php/php-fpm.d/http.pi.conf
 +</code>
 +<file - /etc/php/php-fpm.d/www.conf>
 +[...]
 +pm.max_children = 16
 +[...]
 +pm.start_servers = 9
 +[...]
 +pm.max_spare_servers = 10
 +[...]
 +;env[HOSTNAME] = $HOSTNAME
 +env[PATH] = /usr/local/bin:/usr/bin:/bin
 +env[TMP] = /tmp
 +env[TMPDIR] = /tmp
 +env[TEMP] = /tmp
 +[...]
 +</file>
 +<file - /etc/php/php-fpm.d/http.pi.conf>
 +[...]
 +[http.pi]
 +[...]
 +listen = /run/php-fpm/http.pi_php-fpm.sock
 +[...]
 +</file>
 +<file - /etc/systemd/system/php-fpm.service.d/overwrite-rw-path.conf>[Service]
 +ReadWritePaths = /usr/share/webapps/nextcloud/data
 +ReadWritePaths = /usr/share/webapps/nextcloud/apps
 +ReadWritePaths = /etc/webapps/nextcloud/config/
 +ReadWritePaths = /usr/share/webapps/wordpress/wp-content
 +ReadWritePaths = /usr/share/webapps/invoiceplane/vendor/mpdf/mpdf/tmp
 +ReadWritePaths = /usr/share/webapps/invoiceplane/uploads/archive
 +ReadWritePaths = /usr/share/webapps/invoiceplane/uploads/customer_files
 +</file>
 +
 +===== wordpress =====
 +<code bash>
 +pacman -S wordpress wp-cli wordpress-plugin-antispam-bee wordpress-plugin-code-syntax-block wordpress-plugin-jetpack-lite wordpress-plugin-lightbox-photoswipe wordpress-plugin-wp-gdpr-compliance wordpress-plugin-wp-statistics wordpress-plugin-co-authors-plus wordpress-theme-geist wordpress-plugin-wp-user-avatar wordpress-plugin-opengraph wordpress-plugin-simple-login-captcha wordpress-plugin-disable-xml-rpc wordpress-plugin-async-javascript wordpress-plugin-breeze wordpress-plugin-webp-converter-for-media
 +chown -R http:http /usr/share/webapps/wordpress/wp-admin /usr/share/webapps/wordpress/wp-includes
 +</code>
 +<file - /etc/php/conf.d/wordpress.ini>
 +extension=mysqli
 +</file>
 +<file php /home/pi_wordpress/wordpress/wp-config.php>
 +define('DB_NAME', '****');
 +define('DB_USER', '****');
 +define('DB_PASSWORD', '****');
 +define('DB_HOST', '****');
 +[...]
 +define('AUTH_KEY',         '****');
 +define('SECURE_AUTH_KEY',  '****');
 +define('LOGGED_IN_KEY',    '****');
 +define('NONCE_KEY',        '****');
 +define('AUTH_SALT',        '****');
 +define('SECURE_AUTH_SALT', '****');
 +define('LOGGED_IN_SALT',   '****');
 +define('NONCE_SALT',       '****');
 +[...]
 +define('FORCE_SSL_ADMIN', true);
 +define('FS_METHOD', 'direct');
 +define( 'WP_SITEURL','https://blog.project-insanity.org');
 +define( 'WP_HOME','https://blog.project-insanity.org');
 +$_SERVER['HTTPS']='on';
 +define( 'WP_AUTO_UPDATE_CORE', true );
 +</file>
 +<file - /etc/pacman.d/hooks/wordpress.hook>
 +# Update Wordpress when core or plugins get updated
 +
 +[Trigger]
 +Operation = Install
 +Operation = Upgrade
 +Type = Package
 +Target = wordpress
 +Target = wordpress-plugin-*
 +
 +[Action]
 +Description = Updating Wordpress installation
 +When = PostTransaction
 +Exec = /usr/bin/sh -c "/usr/bin/sudo -u http /usr/bin/bash -c 'wp core update-db --path=/usr/share/webapps/wordpress; wp plugin activate --path=/usr/share/webapps/wordpress antispam-bee code-syntax-block jetpack jetpack-lite lightbox-photoswipe wp-gdpr-compliance wp-statistics co-authors-plus wp-user-avatar opengraph simple-login-captcha disable-xml-rpc async-javascript breeze webp-converter-for-media'"
 +</file>
 +<code bash>
 +sudo -u http wp plugin activate --path=/usr/share/webapps/wordpress antispam-bee code-syntax-block jetpack jetpack-lite lightbox-photoswipe wp-gdpr-compliance wp-statistics co-authors-plus wp-user-avatar opengraph simple-login-captcha disable-xml-rpc async-javascript breeze webp-converter-for-media
 +sudo -u http wp theme activate --path=/usr/share/webapps/wordpress geist
 +</code>
 +Additional CSS for Geist theme
 +<code css>
 +@media (max-width: 1400px) {
 + .single-post .post-content > p:first-child {
 + font-size: 1em;
 + }
 +
 + .single-post .post-content > p, ul {
 + font-size: 0.8em;
 + }
 +
 + .single-post .post-content > h3 {
 + padding-bottom: 0.8em;
 + }
 +</code>
 +Misc settings
 +  * WP Statistics
 +    * Settings -> privacy: "Hash IP Addresses" (GDPR)
 +  * Lightbox with PhotoSwipe
 +    * Enable "Show caption if available"
 +    * Enable "Get image captions from the database"
 +    * Spacing between pictures: 12%
 +  * Settings -> Permalinks -> Custom structure: ''/%year%/%monthnum%/%day%/%postname%/''
 +  * Settings -> General -> 8 posts per page
 +  * Settings -> Discussion -> Show avatar
 +    * Default Avatar -> Mytery Man
 +  * Users -> Your Profile -> Avatar: Choose picture
 +  * Dark mode is not enabled by default. To enable this feature go to Appearance > Customize > Dark Mode.
 +Additional CSS for Ghost theme:
 +<code css>
 +@media (max-width: 1400px) {
 + .single-post .post-content > p:first-child {
 + font-size: 1em;
 + }
 +
 + .single-post .post-content > p, ul {
 + font-size: 0.8em;
 + }
 +
 + .single-post .post-content > h3 {
 + padding-bottom: 0.8em;
 + }
 +}
 +
 +.post-full-content h2 {
 + margin-bottom: 0.8em;
 +}
 +</code>
 +==== co-authors-plus plugin ====
 +template-Anpassung \\
 +[[https://www.wpbeginner.com/plugins/allow-multiple-authors-to-be-associated-with-a-post-in-wordpress/|How to Add Multiple Authors (Co-Authors) for Posts in WordPress]]
 +<file php /home/pi_wordpress/wordpress/functions-content.php> 
 +if ( function_exists( 'coauthors_posts_links' ) ) {
 +    coauthors_posts_links();
 +} else {
 +    the_author_posts_link();
 +}
 +</file>
 +===== invoiceninja =====
 +on mysql.pi
 +<code sql>
 +CREATE SCHEMA `ninja` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
 +CREATE USER 'ninja'@'http.pi' IDENTIFIED BY '****';
 +GRANT ALL PRIVILEGES ON `ninja`.* TO 'ninja'@'http.pi';
 +FLUSH PRIVILEGES;
 +</code>
 +on http.pi
 +<code bash>
 +pacman -S invoiceninja
 +</code>
 +<file - /etc/php/conf.d/composer.ini>
 +extension=gmp
 +</file>
 +<code bash>
 +cd /usr/share/webapps/invoiceninja
 +sudo chown -R http:http storage public/logo bootstrap
 +sudo chown http:http .
 +sudo -u http composer install
 +</code>
 +<file - /etc/caddy/conf.d/http.pi.conf>
 +http://http.pi/invoiceninja {
 +        log /var/log/caddy/http.pi_access.log
 +        errors /var/log/caddy/http.pi_errors.log
 +        gzip
 +
 +        tls off
 +        root /usr/share/webapps/invoiceninja/public
 +        browse
 +
 +        rewrite {
 +                r .*
 +                ext /
 +                to /index.php?{query}
 +        }
 +
 +        fastcgi / /var/run/php-fpm/http.pi_php-fpm.sock php {
 +                index index.php index.htm index.html
 +        }
 +}
 +[...]
 +</file>
 +Settings
 +  * Localization
 +    * Currency: Euro
 +    * Timezone: Berlin
 +    * Date Format: 31.12.2019
 +    * Date/Time Format: 31.12.2019 12:00 am
 +    * 24 Hour Time: Enabled
 +    * First Day of the Week: Monday
 +    * First Month of the Year: January
 +===== invoiceplane =====
 +<code bash>
 +pacman -S invoiceplane composer grunt-cli
 +cd /usr/share/webapps/invoiceplane
 +chown -R http:http .
 +sudo -u http composer install
 +sudo -u http npm install
 +sudo -u http grunt build
 +cp ipconfig.php.example ipconfig.php
 +wget "https://git.project-insanity.org/onny/invoiceplane-vtdirektmarketing/-/raw/master/vtdirektmarketing.php" -O /usr/share/webapps/invoiceplane/application/views/invoice_templates/pdf/vtdirektmarketing.php
 +</code>
 +Visit installation wizard at http://http.pi/invoiceplane/index.php/setup
 +<file - /usr/share/webapps/invoiceplane/ipconfig.php>
 +[...]
 +SETUP_COMPLETED=true
 +DB_HOSTNAME=mysql.pi
 +DB_USERNAME=invoiceplane
 +DB_PASSWORD=****
 +DB_DATABASE=invoiceplane
 +DISABLE_SETUP=true
 +</file>
 +<file - /etc/systemd/system/php-fpm.service.d/overwrite-rw-path.conf>
 +[Service]
 +[...]
 +ReadWritePaths = /usr/share/webapps/invoiceplane/vendor/mpdf/mpdf/tmp
 +ReadWritePaths = /usr/share/webapps/invoiceplane/uploads/archive
 +ReadWritePaths = /usr/share/webapps/invoiceplane/uploads/customer_files
 +</file>
 +Custom settings
 +  * Products -> Product units
 +    * Add: ''Stk.'', ''Std.''
 +  * System-Einstellungen -> Rechnungen
 +    * Standard PDF Vorlage: vtdirektmarketing
 +===== firefox account server =====
 +<code bash>
 +pacaur -S mozilla-firefox-account-server
 +</code>
 +===== podcasttune =====
 +not yet stable
 +===== dokuwiki =====
 +<code bash>
 +pacman -S dokuwiki dokuwiki-plugin-dw2pdf dokuwiki-template-argon
 +</code>
 +<file php /etc/webapps/dokuwiki/local.php>
 +<?php
 +$conf['title'] = 'Project-Insanity';
 +$conf['userewrite' = 1;
 +$conf['template'   = 'argon';
 +</file>
 +<file - /usr/lib/dokuwiki/plugins/dw2pdf/conf/default.php>
 +[...]
 +$conf['doublesided'     = 0;
 +[...]
 +</file>
 +<file - /usr/lib/dokuwiki/plugins/dw2pdf/tpl/default/style.css>
 +@page {
 +    margin-left: 100px;
 +}
 +
 +[...]
 +</file>
 +usage: ''https://wiki.project-insanity.org/onny?do=export_pdf''
 +  * Todo
 +    * DSGVO complience
 +===== gitlab =====
 +<code bash>
 +pacman -S yarn sendmail gitlab
 +ln -s /usr/bin/vendor_perl/exiftool /usr/bin/exiftool # fix for https://gitlab.com/gitlab-org/gitlab-foss/-/issues/60853
 +</code>
 +disable backups
 +<file - /etc/webapps/gitlab/gitlab.yml>
 +[...]
 +  gitlab:
 +    ## Web server settings (note: host is the FQDN, do not include http://)
 +    host: git.project-insanity.org
 +    port: 443 # Set to 443 if using HTTPS, see installation.md#using-https for additional HTTPS configuration details
 +    https: true # Set to true if using HTTPS, see installation.md#using-https for additional HTTPS configuration details
 +[...]
 +  #backup:
 +  #  path: "/var/lib/gitlab/backups"   # Relative paths are relative to Rails.root (default: tmp/backups/)
 +</file>
 +configure database connection
 +<file - /etc/webapps/gitlab/database.yml>
 +production:
 +  adapter: postgresql
 +  encoding: unicode
 +  database: gitlabhq_production
 +  pool: 10
 +  username: gitlab
 +  password: "****"
 +  host: mysql.pi
 +</file>
 +on mysql.pi
 +<code bash>
 +sudo -u postgres psql -d template1 -c "CREATE USER gitlab CREATEDB;"
 +sudo -u postgres psql -d template1 -c "CREATE EXTENSION IF NOT EXISTS pg_trgm;"
 +sudo -u postgres psql -d template1 -c "CREATE DATABASE gitlabhq_production OWNER gitlab;"
 +sudo -u postgres psql -d template1 -c "ALTER USER gitlab WITH SUPERUSER;"
 +</code>
 +on http.pi
 +<code bash>
 + cd /usr/share/webapps/gitlab
 + sudo -u gitlab -H bundle exec rake assets:precompile RAILS_ENV=production
 + sudo -u gitlab -H bundle exec rake gitlab:setup RAILS_ENV=production
 + systemctl enable --now gitlab-workhorse redis gitlab-puma gitlab-sidekiq gitlab-gitaly
 +</code>
 +Enable smtp, mail delivery
 +<file ruby /etc/webapps/gitlab/smtp_settings.rb>
 +# To enable smtp email delivery for your GitLab instance do the following:
 +# 1. Rename this file to smtp_settings.rb
 +# 2. Edit settings inside this file
 +# 3. Restart GitLab instance
 +#
 +# For full list of options and their values see http://api.rubyonrails.org/classes/ActionMailer/Base.html
 +#
 +# If you change this file in a Merge Request, please also create a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
 +
 +if Rails.env.production?
 +  Rails.application.config.action_mailer.delivery_method = :smtp
 +
 +  ActionMailer::Base.delivery_method = :smtp
 +  ActionMailer::Base.smtp_settings = {
 +    address: "mail.pi",
 +    port: 25,
 +    user_name: "git@project-insanity.org",
 +    password: "****",
 +    domain: "project-insanity.org",
 +    authentication: :login,
 +    enable_starttls_auto: false,
 +    openssl_verify_mode: 'none'
 +  }
 +end
 +</file>
 +further general mail settings
 +<file - /etc/webapps/gitlab/gitlab.yml>
 +   ## Email settings
 +    # Uncomment and set to false if you need to disable email sending from GitLab (default: true)
 +    email_enabled: true
 +    # Email address used in the "From" field in mails sent by GitLab
 +    email_from: noreply@project-insanity.org
 +    email_display_name: GitLab
 +    email_reply_to: noreply@project-insanity.org
 +    email_subject_suffix: ''
 +</file>
 +Auto migrate on pacman update
 +<file - /etc/pacman.d/hooks/gitlab.hook>
 +# Update Gitlab when core or other Gitlab daemons are touched
 +
 +[Trigger]
 +Operation = Install
 +Operation = Upgrade
 +Type = Package
 +Target = gitlab
 +Target = gitlab-*
 +
 +[Action]
 +Description = Updating Gitlab installation
 +When = PostTransaction
 +Exec = /usr/bin/sh -c "/usr/bin/systemctl restart gitlab-workhorse gitlab-puma gitlab-sidekiq gitlab-gitaly && cd /usr/share/webapps/gitlab && /usr/bin/sudo -u gitlab $(cat /usr/share/webapps/gitlab/environment | xargs) /usr/bin/bash -c 'cd /usr/share/webapps/gitlab; bundle-2.7 exec rake db:migrate'"
 +</file>
 +<file - /etc/webapps/gitlab/secrets.yml>
 +****
 +</file>
 +<code bash>
 +hexdump -v -n 64 -e '1/1 "%02x"' /dev/urandom > /etc/webapps/gitlab/secret
 +hexdump -v -n 64 -e '1/1 "%02x"' /dev/urandom > /etc/webapps/gitlab-shell/secret
 +chown root:gitlab /etc/webapps/gitlab/secret /etc/webapps/gitlab-shell/secret
 +chmod 640 /etc/webapps/gitlab/secret /etc/webapps/gitlab-shell/secret
 +</code>
 +misc settings:
 +  * enable recaptcha for registration https://docs.gitlab.com/ee/integration/recaptcha.html
 +  * disable ssh git protocol: Admin -> Settings -> Expand "Visibility and access controls" -> For "Enabled Git access protocols" select "Only HTTP(S)"
 +===== onlyoffice documentserver =====
 +<code bash>
 +pacman -S npm nodejs rabbitmq redis onlyoffice-documentserver
 +ln -s /usr/share/libalpm/hooks/onlyoffice-documentserver.hook /etc/pacman.d/hooks/
 +</code>
 +on mysql.pi
 +<code bash>
 +sudo -i -u postgres psql -c "CREATE DATABASE onlyoffice;"
 +sudo -i -u postgres psql -c "CREATE USER onlyoffice WITH password 'onlyoffice';"
 +sudo -i -u postgres psql -c "GRANT ALL privileges ON DATABASE onlyoffice TO onlyoffice;"
 +psql -hmysql.pi -Uonlyoffice -d onlyoffice -f /usr/share/webapps/onlyoffice/documentserver/server/schema/postgresql/createdb.sql
 +</code>
 +<file - /etc/caddy/conf.d/office.project-insanity.org.conf>
 +office.project-insanity.org {
 +    log /var/log/caddy/office.project-insanity.org_access.log
 +    errors /var/log/caddy/office.project-insanity.org_errors.log
 +
 +    proxy /spellchecker http://localhost:8081 {
 +        transparent
 +        websocket
 +        without /spellchecker
 +    }
 +
 +    rewrite {
 +        r ^/(cache|downloadas|sdkjs|plugins.json|fonts|web-apps|upload|doc)/
 +        to /proxy/{uri}
 +    }
 +
 +    proxy /proxy/ http://localhost:8000 {
 +        websocket
 +        transparent
 +        without /proxy/
 +    }
 +
 +    proxy / http://localhost:8082 {
 +        transparent
 +    }
 +}
 +</file>
 +<file - /etc/webapps/onlyoffice/documentserver/default.json>
 +[...]
 +                        "sql": {
 +                                "type": "postgres",
 +                                "tableChanges": "doc_changes",
 +                                "tableResult": "task_result",
 +                                "dbHost": "mysql.pi",
 +                                "dbPort": 5432,
 +                                "dbName": "onlyoffice",
 +                                "dbUser": "onlyoffice",
 +                                "dbPass": "onlyoffice",
 +                                "charset": "utf8",
 +                                "connectionlimit": 10,
 +                                "max_allowed_packet": 1048575
 +                        },
 +[...]
 +       "SpellChecker": {
 +                "server": {
 +                        "port": 8081,
 +                        "mode": "development"
 +                }
 +        }
 +</file>
 +<file - /etc/hosts>
 +10.25.0.100 nextcloud.project-insanity.org
 +</file>
 +<code bash>
 +systemctl enable --now rabbitmq redis onlyoffice-docservice onlyoffice-fileconverter onlyoffice-spellchecker
 +</code>
 +==== officepad ====
 +<file - /etc/systemd/system/officepad.service>
 +[Unit]
 +Description=Documentserver integration example
 +
 +[Service]
 +User=http
 +WorkingDirectory=/usr/share/webapps/officepad
 +ExecStart=/usr/bin/node bin/www
 +
 +[Install]
 +WantedBy=basic.target
 +</file>
 +<code bash>
 +sudo git clone git clone https://git.project-insanity.org/onny/officepad.git /usr/share/webapps/officepad
 +sudo chown -R http:http /usr/share/webapps/officepad
 +systemd daemon-reload
 +systemctl enable --now officepad
 +</code>
 +<file - /usr/share/webapps/officepad/config/default.json>
 +[...]
 +siteUrl": "https://bwsas-prod-oo-02.lsdf.kit.edu/"
 +[...]
 +</file>
 + ===== nextcloud =====
 +<code bash>
 +pacman -S php-imagick php-intl nextcloud nextcloud-app-twofactor-gateway nextcloud-app-audioplayer nextcloud-app-polls nextcloud-app-extract nextcloud-app-suspicious-login nextcloud nextcloud-app-mail nextcloud-app-news nextcloud-app-calendar nextcloud-app-contacts nextcloud-app-keeweb nextcloud-app-deck nextcloud-app-onlyoffice nextcloud-app-bookmarks nextcloud-app-notes nextcloud-app-talk nextcloud-integration-github nextcloud-integration-twitter nextcloud-integration-reddit nextcloud-integration-discourse nextcloud-app-radio nextcloud-app-podcast
 +</code>
 +<file - /etc/php/php-fpm.d/www.conf>
 +env[PATH] = /usr/local/bin:/usr/bin:/bin
 +env[TMP] = /tmp
 +env[TMPDIR] = /tmp
 +env[TEMP] = /tmp
 +</file>
 +php performance optimizations
 +<file - /etc/php/conf.d/nextcloud.ini>
 +memory_limit = 512M
 +
 +extension=gd
 +extension=pdo_mysql
 +extension=apcu
 +extension=intl
 +extension=iconv
 +extension=imagick
 +extension=bcmath
 +
 +# Nextcloud recommended performance settings
 +zend_extension=opcache.so
 +opcache.enable=1
 +opcache.enable_cli=1
 +opcache.interned_strings_buffer=8
 +opcache.max_accelerated_files=10000
 +opcache.memory_consumption=128
 +opcache.save_comments=1
 +opcache.revalidate_freq=1
 +
 +apc.enable_cli=1
 +</file>
 +<file - /usr/share/webapps/nextcloud/conf/config.php>
 +<?php
 +$CONFIG = array (
 +  'instanceid' => '****',
 +  'passwordsalt' => '****',
 +  'datadirectory' => '/usr/share/webapps/nextcloud/data',
 +  'dbtype' => 'mysql',
 +  'version' => '19.0.0.12',
 +  'dbname' => 'nextcloud',
 +  'dbhost' => 'mysql.pi',
 +  'dbtableprefix' => 'oc_',
 +  'mysql.utf8mb4' => true,
 +  'dbuser' => 'nextcloud',
 +  'dbpassword' => '****',
 +  'installed' => true,
 +  'theme' => '',
 +  'maintenance' => false,
 +  'loglevel' => 0,
 +  'cron_log' => true,
 +  'maxZipInputSize' => 5145728000,
 +  'allowZipDownload' => true,
 +  'memcache.local' => '\\OC\\Memcache\\APCu',
 +  'allow_local_remote_servers' => true,
 +  'trusted_domains' => 
 +  array (
 +    0 => 'nextcloud.project-insanity.org',
 +    1 => 'http.pi',
 +    2 => 'office.project-insanity.org',
 +  ),
 +  'secret' => '****',
 +  'mail_domain' => 'project-insanity.org',
 +  'mail_smtpmode' => 'php',
 +  'mail_from_address' => 'nextcloud',
 +  'trashbin_retention_obligation' => 'auto',
 +  'updatechecker' => false,
 +  'has_internet_connection' => false,
 +  'app.mail.verify-tls-peer' => false,
 +  'app_install_overwrite' => 
 +  array (
 +    0 => 'apporder',
 +    1 => 'keeweb',
 +    2 => 'tasks',
 +    3 => 'weather',
 +    4 => 'audioplayer',
 +    5 => 'files_ebookreader',
 +    6 => 'extract',
 +    7 => 'polls',
 +    8 => 'onlyoffice',
 +    9 => 'drawio',
 +  ),
 +);
 +</file>
 +Due to [[https://bugs.archlinux.org/task/64689?project=5&string=nextcloud|packaging bug]] and hardened php-fpm.service file, an unit file overwrite is required:
 +<file - /etc/systemd/system/php-fpm.service.d/overwrite-rw-path.conf>
 +[Service]
 +[...]
 +ReadWritePaths = /usr/share/webapps/nextcloud/data
 +ReadWritePaths = /usr/share/webapps/nextcloud/apps
 +ReadWritePaths = /etc/webapps/nextcloud/config/
 +ReadWritePaths = /usr/share/webapps/wordpress/wp-content
 +</file>
 +Auto upgrade on pacman update
 +<code bash>
 +ln -sv /usr/share/doc/nextcloud/nextcloud.hook /etc/pacman.d/hooks/
 +</code>
 +<file - /etc/pacman.d/hooks/nextcloud-enable-apps.hook>
 +# Update Nextcloud when core or -apps are touched
 +
 +[Trigger]
 +Operation = Install
 +Operation = Upgrade
 +Type = Package
 +Target = nextcloud
 +Target = nextcloud-app-*
 +
 +[Action]
 +Description = Updating Nextcloud installation
 +When = PostTransaction
 +Exec = /usr/bin/sh -c "/usr/bin/chown -R nextcloud:nextcloud /usr/share/webapps/nextcloud/apps && /usr/bin/sudo -u nextcloud /usr/bin/php /usr/share/webapps/nextcloud/occ app:enable twofactor_gateway audioplayer polls extract suspicious_login mail news calendar contacts keeweb deck onlyoffice bookmarks notes talk integration_github integration_twitter integration_reddit integration_discourse radio podcast"
 +</file>
 +Nextcloud background job (cron)
 +<file -/etc/systemd/system/nextcloudcron.service>
 +[Unit]
 +Description=Nextcloud cron.php job
 +
 +[Service]
 +User=nextcloud
 +ExecStart=/usr/bin/php -f /usr/share/webapps/nextcloud/cron.php
 +
 +[Install]
 +WantedBy=basic.target
 +</file>
 +<file - /etc/systemd/system/nextcloudcron.timer>
 +[Unit]
 +Description=Run Nextcloud cron.php every 15 minutes
 +
 +[Timer]
 +OnBootSec=5min
 +OnUnitActiveSec=15min
 +Unit=nextcloudcron.service
 +
 +[Install]
 +WantedBy=timers.target
 +</file>
 +<code bash>
 +systemctl enable --now nextcloudcron.timer
 +</code>
 +Add additional mimetype for keeweb app
 +<code bash>
 +cd /usr/share/webapps/nextcloud
 +cp resources/config/mimetypemapping.dist.json config/mimetypemapping.json
 +</code>
 +add kdbx line to json config
 +<file - /usr/share/webapps/nextcloud/config/mimetypemapping.json>
 +[...]
 +        "_comment4": "Any changes you make here will be overwritten on an update of Nextcloud",
 +        "_comment5": "Put any custom mappings in a new file mimetypemapping.json in the config/ folder of Nextcloud",
 +
 +        "kdbx": ["x-application/kdbx"],
 +        "3gp": ["video/3gpp"],
 +        "7z": ["application/x-7z-compressed"],
 +[...]
 +</file>
 +<code bash>
 +occ app:enable twofactor_gateway audioplayer polls extract suspicious_login mail news calendar contacts keeweb deck onlyoffice bookmarks notes talk integration_github integration_twitter integration_reddit integration_discourse radio podcast
 +</code>
 +==== mail ====
 +disable ssl verification of imap/smpt host
 +<file - /usr/share/webapps/nextcloud/config/config.php>
 +[...]
 +  'app.mail.verify-tls-peer' => false,
 +[...]
 +</file>
 +==== twofactor_gateway ====
 +disposible phone number registration http://www.getsmscode.com
 +<file - /etc/webapps/signal-web-gateway/config.yml>
 +[...]
 +tel: "+1774****"
 +[...]
 +</file>
 +<code bash>
 +cd /usr/share/webapps/nextcloud
 +sudo -u http ./occ twofactorauth:gateway:configure signal # leave default options (press return)
 +cd /var/lib/signal-web-gateway
 +sudo -u signal signal-web-gateway # enter verification
 +systemctl enable --now signal-web-gateway
 +</code>
 +  * Activate 2FA in ''Settings -> Security (User)''
 +    * Enter your phone number and press verify
 +
 +==== onlyoffice ====
 +  * Paste in ''Settings -> ONLYOFFICE'' the ''Document Editing Service address'' to ''https://office.project-insanity.org''
 +==== mantainance ====
 +Run file integrity checks
 +<code bash>
 +sudo -u http /usr/share/webapps/nextcloud/occ integrity:check-app
 +sudo -u http /usr/share/webapps/nextcloud/occ integrity:check-core
 +sudo -u http /usr/share/webapps/nextcloud/occ files:scan --all
 +</code>
 +===== phpmyadmin =====
 +<file - /etc/webapps/phpmyadmin/config.inc.php>
 +[...]
 +/* Server parameters */
 +$cfg['Servers'][$i]['host'] = 'mysql.pi';
 +$cfg['Servers'][$i]['compress'] = false;
 +[...]
 +</file>
 +
 +
 +===== cockpit =====
 +<code bash>
 +pacman -S cockpit
 +systemctl enable --now cockpit pmcd
 +useradd -m cockpit
 +passwd cockpit
 +nft add rule inet filter input position 17 ip saddr 10.25.40.0/24 tcp dport 9090 accept
 +nft add rule inet filter input position 17 ip6 saddr 2a01:4f8:191:327::0/64 tcp dport 9090 accept
 +nft list ruleset > /etc/nftables.conf
 +</code>
 +<file - /etc/sudoers>
 +[...]
 +cockpit ALL=(ALL) ALL
 +[...]
 +</file>
 +<file - /etc/pam.d/cockpit>
 +#%PAM-1.0
 +
 +auth      required  pam_unix.so     try_first_pass nullok
 +auth      optional  pam_permit.so
 +auth      required  pam_env.so
 +
 +account   required  pam_unix.so
 +account   optional  pam_permit.so
 +account   required  pam_time.so
 +
 +password  required  pam_unix.so     try_first_pass nullok sha512 shadow
 +password  optional  pam_permit.so
 +
 +session   required  pam_limits.so
 +session   required  pam_unix.so
 +session   optional  pam_permit.so
 +</file>
 +
 +===== outline =====
 +on http.pi
 +<code bash>
 +pacman -S outline
 +</code>
 +<file - /etc/webapps/outline/.env>
 +[...]
 +SECRET_KEY=****
 +DATABASE_URL=postgres://outline:outline@mysql.pi:5432/outline
 +REDIS_URL=redis://localhost:6379
 +URL=http://playground.pi:3000
 +FORCE_HTTPS=false
 +</file>
 +on mysql.pi
 +<code bash>
 +sudo -i -u postgres psql -c "CREATE DATABASE outline;"
 +sudo -i -u postgres psql -c "CREATE USER outline WITH password 'outline';"
 +sudo -i -u postgres psql -c "GRANT ALL privileges ON DATABASE outline TO outline;"
 +</code>
 +on http.pi
 +<code bash>
 +cd /usr/share/webapps/outline
 +npm run sequelize:migrate
 +systemctl enable --now outline
 +</code>
 +
 +====== storage.pi ======
 +===== kol ha campus archive radio stream =====
 +<code bash>
 +pacman -S vlc pulseaudio
 +</code>
 +<file - /etc/systemd/system/106fm_archive_stream.service>
 +[Unit]
 +Description=160fm.co.il archive radio stream server
 +After=network-online.target 
 +
 +[Service]
 +User=onny
 +Type=simple
 +ExecStart=/usr/bin/cvlc -A pulse,none /home/onny/bash-kolhaas-archive/archived --loop --random --sout-keep --sout '#transcode{acodec=opus}:duplicate{dst=display{delay=6000},dst=gather:std{mux=ffmpeg{mux=opus},dst=:8080,access=http},select="novideo"}'
 +Restart=on-abort
 +
 +[Install]
 +WantedBy=multi-user.target
 +</file>
 +<file - /usr/lib/systemd/system/pulseaudio.service>
 +[Unit]
 +Description=PulseAudio system server
 +
 +[Service]
 +ExecStart=/usr/bin/pulseaudio --system --daemonize=no --disallow-exit --log-target=journal
 +ExecReload=/bin/kill -HUP $MAINPID
 +
 +[Install]
 +WantedBy=multi-user.target
 +</file>
 +<file - /usr/share/dbus-1/system.d/pulseaudio.conf>
 +<?xml version="1.0"?> <!--*-nxml-*-->
 +<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
 + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
 +<busconfig>
 +    <policy group="pulse">
 +        <allow own="org.pulseaudio.Server"/>
 +    </policy>
 +
 +    <policy context="default">
 +        <allow send_destination="org.pulseaudio.Server"/>
 +        <allow receive_sender="org.pulseaudio.Server"/>
 +    </policy>
 +</busconfig>
 +</file>
 +<code bash>
 +echo "default-server = /var/run/pulse/native" >> /etc/pulse/client.conf
 +echo "autospawn = no" >> /etc/pulse/client.conf
 +systemctl daemon-reload
 +groupadd --system pulse
 +groupadd --system pulse-access
 +useradd --system -g pulse -G audio -d /var/run/pulse -m pulse
 +gpasswd -a onny audio,pulse-acces
 +systemctl enable --now pulseaudio 106fm_archive_stream
 +nft add rule inet filter input position 17 ip saddr 10.25.0.0/24 tcp dport 8080 accept
 +nft add rule inet filter input position 17 ip6 saddr 2a01:4f8:191:327::0/64 tcp dport 8080 accept
 +nft list ruleset > /etc/nftables.conf
 +</code>
 +also added a caddy rule on http.pi for the url: https://blog.project-insanity.org/106fm
 +===== bitcoind =====
 +<code bash>
 +pacman -S bitcoin-daemon
 +systemctl start bitcoind
 +systemctl enable bitcoind
 +ufw allow from 10.25.0.0/24 to any port 8333
 +</code>
 +https://bitcoin.stackexchange.com/a/75312
 +====== playground.pi ======
 +<code bash>
 +pacman -S devtools
 +</code>
 +===== beta.saai.digital =====
 +<code bash>
 +pacman -S iptables-nft
 +</code>
 +<file - /etc/nftables.conf>
 +[...]
 +chain forward {
 +  type filter hook forward priority security; policy drop;
 +  mark 1 accept
 +[...]
 +table ip filter {
 +  chain DOCKER-USER {
 +    mark set 1
 +  }
 +}
 +</file>
 +<code bash>
 +systemctl enable --now docker
 +</code>
 +===== QuakeJS =====
 +<code bash>
 +pacman -S quakejs-git
 +cd /usr/share/webapps/quakejs
 +chown -R quakejs:quakejs .
 +sudo -u quakejs node build/ioq3ded.js +set fs_game baseq3 +set dedicated 2
 +</code>
 +<file - /etc/conf.d/quakejs>
 +QUAKEJS_DS_PARAMS="+set fs_cdn cdn.quake.turbotux.de +set fs_game baseq3 +set dedicated 1 +exec server.cfg"
 +</file>
 +<file - /usr/share/webapps/quakejs/base/baseq3/server.cfg>
 +seta sv_hostname "Project-Insanity.org QuakeJS"
 +seta sv_maxclients 12
 +seta g_motd "Welcome to PI Quake 3 battleground"
 +seta g_quadfactor 3
 +seta g_gametype 0
 +seta timelimit 15
 +seta fraglimit 25
 +seta g_weaponrespawn 3
 +seta g_inactivity 3000
 +seta g_forcerespawn 0
 +seta rconpassword "CHANGE_ME"
 +set d1 "map q3dm17 ; set nextmap vstr d2"
 +set d2 "map q3tourney3 ; set nextmap vstr d3"
 +set d3 "map q3tourney1 ; set nextmap vstr d1"
 +vstr d1
 +</file>
 +<file - /etc/webapps/quakejs/web.json>
 +
 +        "content": "cdn.quake.turbotux.de",
 +        "port": 8081
 +}
 +</file>
 +<code bash>
 +systemctl enable --now quakejs-ds quakejs quakejs-cdn
 +</code>
 +===== PI ArchLinux Repository =====
 +build and install auruitls from source
 +<code bash>
 +cd /tmp
 +curl "https://aur.archlinux.org/cgit/aur.git/snapshot/aurutils.tar.gz" | tar xz
 +cd aurutils
 +gpg --recv-keys DBE7D3DD8C81D58D0A13D0E76BC26A17B9B7018A 
 +makepkg -i
 +pacman --root=/var/lib/aurbuild/x86_64/root -S git
 +pacman --root=/var/lib/aurbuild/x86_64/root -S python2-setuptools # workaround for zeronet -> python-pyelliptic
 +pacman --root=/var/lib/aurbuild/x86_64/root -S wayland # workaround for dmenu-wayland-git
 +sudo /usr/share/devtools/pacman-extra.conf /etc/aurutils/pacman-projectinsanity.conf
 +</code>
 +configure custom repository
 +<file - /etc/pacman.conf>
 +[...]
 +Include = /etc/pacman.d/projectinsanity
 +</file>
 +<file - /etc/pacman.d/projectinsanity>
 +[options]
 +CacheDir = /var/cache/pacman/pkgwf
 +CacheDir = /var/cache/pacman/projectinsanity
 +CleanMethod = KeepCurrent
 +
 +[aur]
 +SigLevel = Optional TrustAll
 +Server = file:///var/cache/pacman/projectinsanity
 +</file>
 +<file - /etc/suders>
 +[...]
 +aur ALL = NOPASSWD: SETENV: /usr/bin/makechrootpkg
 +aur ALL = NOPASSWD: /usr/bin/arch-nspawn
 +[...]
 +</file>
 +<code bash>
 +sudo useradd -m aur
 +sudo install -d /var/cache/pacman/projectinsanity -o aur
 +sudo repo-add /var/cache/pacman/projectinsanity/projectinsanity.db.tar
 +sudo chown -R aur:aur /var/cache/pacman/projectinsanity
 +sudo -u aur gpg --recv-keys 6BC26A17B9B7018A
 +sudo -u aur gpg --recv-keys 1D1F0DC78F173680
 +</code>
 +<file - /etc/systemd/system/aurupdate.service>
 +[Unit]
 + Description=Automatic update AUR repository.
 + After=network-online.target 
 +
 +[Service]
 + Type=simple
 + User=aur
 + ExecStart=/usr/bin/pi-archlinuxrepo-update.sh
 + TimeoutStopSec=180
 + KillMode=process
 + KillSignal=SIGINT
 +
 +[Install]
 + WantedBy=multi-user.target
 +</file>
 +<file - /usr/bin/pi-archlinuxrepo-update.sh>
 +#!/bin/bash
 +for package in $(pacman -Sql projectinsanity) 
 +do
 +  aur sync --no-view -c $package
 +done
 +</file>
 +<file - /etc/systemd/system/aurupdate.timer>
 +[Unit]
 + Description=Automatic update AUR repository when booted up after 5 minutes then check for updates every 60 minutes.
 +
 +[Timer]
 + OnBootSec=5min
 + OnUnitActiveSec=120min
 + Unit=aurupdate.service
 +
 +[Install]
 + WantedBy=multi-user.target
 +</file>
 +<code bash>
 +systemctl enable --now aurupdate.timer
 +</code>
 +<code bash>
 +sudo -u aur gpg --recv-keys 2A349DD577D586A5
 +sudo -u aur aur sync -d projectinsanity -c librewolf pkgbuild-introspection tor-browser-en r128gain split2flac id3ted redshift-wlr-gamma-control-git krop wcalc anbox-git ocenaudio-bin smloadr soulseekqt aurutils downgrade maddy wp-cli wordpress-plugin-antispam-bee wordpress-plugin-code-syntax-block wordpress-plugin-jetpack-lite wordpress-plugin-lightbox-photoswipe wordpress-plugin-wp-gdpr-compliance wordpress-plugin-wp-statistics jellyfin onlyoffice-documentserver nextcloud-app-twofactor-gateway nextcloud-app-audioplayer nextcloud-app-polls nextcloud-app-extract nextcloud-app-suspicious-login nextcloud-app-keeweb nextcloud-app-radio nextcloud-app-onlyoffice fdroidserver android-sdk android-sdk-build-tools gplaycli vlc-bittorrent qlcplus signal-web-gateway-git invoiceninja invoiceplane python-gspread-git etcher zeronet teamviewer scrcpy ttyd wdisplays-git dmenu-wayland-git python-soundcard python-soundfile pacaur archivemount micro python-rpi.gpio python-pad4pi python-pulse-control python-rplcd python-vlc python-mpv pmbootstrap wordpress-theme-geist linux-libre opensnitch-git powerpill osmctools tilemaker nextcloud-app-talk xerox-phaser-6000-6010 dokuwiki-plugin-captcha dokuwiki-plugin-dw2pdf dokuwiki-template-argon nextcloud-integration-github nextcloud-integration-twitter nextcloud-integration-reddit nextcloud-integration-discourse wordpress-plugin-opengraph nextcloud-app-podcast wordpress-plugin-simple-login-captcha wordpress-plugin-disable-xml-rpc wordpress-plugin-async-javascript wordpress-plugin-breeze wordpress-plugin-webp-converter-for-media
 +pacman -S caddy
 +gpasswd -a caddy http
 +systemctl enable --now caddy
 +nft add rule inet filter input position 17 ip saddr 10.25.0.0/24 tcp dport http accept
 +nft add rule inet filter input position 17 ip6 saddr 2a01:4f8:191:327::0/64 tcp dport http accept
 +nft list ruleset > /etc/nftables.conf
 +</code>
 +caddy configuration
 +<file - /etc/caddy/Caddyfile
 +import conf.d/*.conf
 +</file>
 +<file - /etc/caddy/conf.d/onny.project-insanity.org.conf>
 +http://onny.project-insanity.org {
 +
 +        log {
 +                output file     /var/log/caddy/onny.project-insanity.org.log
 +                format single_field common_log
 +        }
 +
 +    handle /archlinux {
 +        redir https://onny.project-insanity.org/archlinux/
 +    }
 +
 +    handle /archlinux/* {
 +        root * /var/cache/pacman/projectinsanity
 +        uri strip_prefix /archlinux
 +            file_server browse
 +    }
 +
 +}
 +</file>
 +<code bash>
 +systemctl restart caddy
 +</code>
 +caddy configuration on http-pub.pi:
 +<file - /etc/caddy/conf.d/onny.project-insanity.org.conf>
 +[...]
 +    proxy /archlinux playground.pi {
 +        transparent
 +    }
 +[...]
 +</file>
 +<code bash>
 +systemctl restart caddy
 +</code>
 +====== http-pub.pi ======
 +<code bash>
 +pacman -S caddy php-fpm
 +systemctl enable --now caddy php-fpm
 +nft add rule inet filter input position 17 ip saddr 10.25.0.0/24 tcp dport http accept
 +nft add rule inet filter input position 17 ip6 saddr 2a01:4f8:191:327::0/64 tcp dport http accept
 +nft list ruleset > /etc/nftables.conf
 +</code>
 +<file - /etc/pacman.d/hooks/php.hook>
 +# Restart php service
 +
 +[Trigger]
 +Operation = Install
 +Operation = Upgrade
 +Type = Package
 +Target = php
 +Target = php-fpm
 +
 +[Action]
 +Description = Restarting php service
 +When = PostTransaction
 +Exec = /usr/bin/systemctl restart php-fpm
 +</file>
 +custom caddy installation
 +<code bash>
 +pacaur -d caddy
 +</code>
 +<file - ~/.cache/pacaur/caddy/PKGBUILD>
 +[...]
 +#    'http.expires'
 +    'http.filemanager'
 +#    'http.filter'
 +[...]
 +</file>
 +<code bash>
 +cd ~/.cache/pacaur/caddy
 +makepkg -i --skipinteg
 +</code>
 +===== caddy =====
 +<code bash>
 +pacman -S caddy
 +gpasswd -a caddy http
 +</code>
 +<file - /etc/caddy/Caddyfile>
 +import /etc/caddy/conf.d/*
 +</file>
 +<file - /etc/caddy/conf.d/ausstellung-virtuell.de.conf>
 +http://ausstellung-virtuell.de {
 +    redir https://www.ausstellung-virtuell.de{uri}
 +}
 +
 +http://www.ausstellung-virtuell.de {
 +
 +        root    * /var/www/ausstellung-virtuell.de
 +        file_server
 +        log {
 +                output file     /var/log/caddy/ausstellung-virtuell.de.log
 +                format single_field common_log
 +        }
 +
 +        php_fastcgi unix//var/run/php-fpm/ausstellung-virtuell.de_php-fpm.sock
 +
 +        @mainpage {
 +          path_regexp path ^/([^.]+)$
 +        }
 +        rewrite @mainpage /index.php?page={http.regexp.path.1}
 +}
 +</file>
 +<file - /etc/caddy/conf.d/onny.project-insanity.org.conf>
 +http://onny.project-insanity.org {
 +
 +        reverse_proxy /archlinux* playground.pi:80
 +        
 +        root    * /var/www/onny.project-insanity.org
 +        file_server
 +        log {
 +                output file     /var/log/caddy/onny.project-insanity.org.log
 +                format single_field common_log
 +        }
 +
 +        php_fastcgi unix//var/run/php-fpm/onny.project-insanity.org_php-fpm.sock
 +
 +}
 +</file>
 +<file - /etc/systemd/system/caddy.service.d/overwride.conf>
 +[Service]
 +ProtectHome=false
 +LimitNOFILE=infinity
 +LimitNPROC=infinity
 +</file>
 +<code bash>
 +systemctl daemon-reload
 +systemctl restart caddy
 +</code>
 +Overwrite php-fpm.service configuration, allow access to home directories:
 +<file - php-fpm.service.d/overwrite.conf>
 +[Service]
 +ProtectHome=false
 +</file>
 +
 +===== wordpress =====
 +<file - /etc/php/conf.d/wordpress.ini>
 +extension=mysqli
 +
 +upload_max_filesize = 64M
 +post_max_size = 64M
 +</file>
 +
 +===== uwsgi =====
 +<code bash>
 +pacman -S uwsgi-plugin-python python-bottle
 +mkdir /etc/uwsgi/systemd
 +</code>
 +<file - /etc/systemd/system/uwsgi-private@.service>
 +[Unit]
 +Description=uWSGI service unit
 +After=syslog.target
 +
 +[Service]
 +ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/%I.ini
 +Type=notify
 +SuccessExitStatus=15 17 29 30
 +NotifyAccess=all
 +KillSignal=SIGQUIT
 +PrivateDevices=yes
 +PrivateTmp=yes
 +ProtectSystem=full
 +CapabilityBoundingSet=CAP_SETGID CAP_SETUID
 +ReadWriteDirectories=${rw_directory}
 +ProtectHome=yes
 +NoNewPrivileges=yes
 +EnvironmentFile=/etc/uwsgi/systemd/%i.conf
 +
 +[Install]
 +WantedBy=multi-user.target
 +</file>
 +<file - /etc/systemd/system/uwsgi-private@.socket>
 +[Unit]
 +Description=Socket for uWSGI %I
 +
 +[Socket]
 +# Change this to your uwsgi application port or unix socket location
 +ListenStream=/run/uwsgi/%I.sock
 +
 +[Install]
 +WantedBy=sockets.target
 +</file>
 +==== getmetadata ====
 +<code bash>
 +pacman -S python-requests
 +</code>
 +<file - /etc/uwsgi/getmetadata.ini>
 +[uwsgi]
 +http-socket = /run/uwsgi/%n.sock
 +uid = http
 +gid = http
 +chdir = /usr/share/webapps/getmetadata
 +master = true
 +plugins = python
 +file = streammetadata-api.py
 +</file>
 +<file - /etc/uwsgi/systemd/getmetadata.conf>
 +rw_directory="/usr/share/webapps/getmetadata"
 +</file>
 +<code bash>
 +systemctl enable uwsgi-private@getmetadata
 +systemctl start uwsgi-private@getmetadata
 +</code>
 +==== biolaedle-etiketten-generator ====
 +<code bash>
 +pacman -S python-pandas python-reportlab python-xlrd python-bottle
 +</code>
 +<file - /etc/uwsgi/biolaedle-etiketten-generator.ini>
 +[uwsgi]
 +http-socket = /run/uwsgi/%n.sock
 +uid = http
 +gid = http
 +chdir = /usr/share/webapps/biolaedle-etiketten-generator
 +master = true
 +plugins = python
 +file = label.py
 +</file>
 +<code bash>
 +systemctl enable --now uwsgi@biolaedle\\x2detiketten\\x2dgenerator
 +</code>
 +
 +==== feeds ====
 +<code bash>
 +pacman -S python-feedparser python-beautifulsoup4 python-pyrss2gen python-dateutil python-lxml
 +</code>
 +<file - /etc/uwsgi/feeds.ini>
 +[uwsgi]
 +http-socket = /run/uwsgi/%n.sock
 +uid = http
 +gid = http
 +chdir = /usr/share/webapps/feeds
 +master = true
 +plugins = python
 +file = app.py
 +</file>
 +<file - /etc/uwsgi/systemd/feeds.conf>
 +rw_directory="/usr/share/webapps/feeds"
 +</file>
 +<code bash>
 +systemctl enable uwsgi-private@feeds
 +systemctl start uwsgi-private@feeds
 +</code>
 +==== pishare ====
 +<code bash>
 +pacman -S nodejs
 +</code>
 +<file - /etc/uwsgi/pishare.ini>
 +[uwsgi] 
 +httpsocket = /run/uwsgi/%n.sock
 +uid = http
 +gid = http
 +chdir = /usr/share/webapps/pishare
 +master = true
 +threads = true
 +plugins = python
 +file = pishare.py
 +lazy-apps = true
 +</file>
 +<code bash>
 +systenmctl enable --now uwsgi@pishare
 +</code>
 +
 +===== arch-upstream =====
 +<code bash>
 +pacman -S python-progressbar python-jinja
 +ln -s /usr/share/webapps/arch-upstream /var/www/onny.sexypump.de/
 +</code>
 +<file - /etc/systemd/system/arch-upstream.service>
 +[Unit]
 +Description=Arch-Upstream
 +
 +[Service]
 +Type=simp
 +User=http
 +Group=http
 +PrivateDevices=yes
 +PrivateTmp=yes
 +ProtectSystem=full
 +CapabilityBoundingSet=
 +ReadWriteDirectories=/usr/share/webapps/arch-upstream
 +ProtectHome=yes
 +NoNewPrivileges=yes
 +WorkingDirectory=/usr/share/webapps/arch-upstream
 +ExecStart=/usr/share/webapps/arch-upstream/main.py
 +</file>
 +<file - /etc/systemd/system/arch-upstream.timer>
 +[Unit]
 +Description=Run arch-upstream every 12 hours
 +
 +[Timer]
 +# Time to wait after booting before we run first time
 +OnBootSec=10min
 +# Time between running each consecutive time
 +OnUnitActiveSec=12h
 +Unit=arch-upstream.service
 +
 +[Install]
 +WantedBy=multi-user.target
 +</file>
 +<code bash>
 +systemctl enable arch-upstream.timer
 +systemctl start arch-upstream.timer
 +</code>
 +===== fdroid repo gplay mirror =====
 +http-pub.pi
 +
 +enable multilib
 +<file - /etc/pacman.conf>
 +[...]
 +#[multilib-testing]
 +#Include = /etc/pacman.d/mirrorlist
 +
 +[multilib]
 +Include = /etc/pacman.d/mirrorlist
 +
 +# An example of a custom package repository.  See the pacman manpage for
 +# tips on creating your own repositories.
 +[...]
 +</file>
 +<code bash>
 +pacman -S fdroidserver android-sdk android-sdk-build-tools gplaycli
 +cd www
 +mkdir fdroid
 +cd fdroid
 +env ANDROID_HOME=/opt/android-sdk fdroid init
 +</code>
 +<file - www/fdroid/config.py>
 +[...]
 +repo_url = "https://onny.project-insanity.org/fdroid/repo"
 +repo_name = "Project-Insanity F-Droid repo"
 +repo_icon = "fdroid-icon.png"
 +repo_description = "This is a private F-Droid repository for the PI-crew :)"
 +[...]
 +</file>
 +<code bash>
 +env ANDROID_HOME=/opt/android-sdk fdroid update --create-metadata
 +</code>
 +<code bash>
 +mkdir ~/.config/gplaycli
 +</code>
 +<file - ~/.config/gplaycli/gplaycli.conf>
 +[Credentials]
 +gmail_address=****@gmail.com
 +gmail_password=****
 +token=False
 +</file>
 +<file - ~/.config/gplaycli/apk.list>
 +org.thoughtcrime.securesms
 +de.nextbike
 +com.spotify.music
 +com.mobiledirection.GPSRepairFix
 +com.melodis.midomiMusicIdentifier.freemium
 +com.whatsapp
 +de.hafas.android.db
 +de.regiorad.stuttgart
 +com.ebay.mobile
 +com.ebay.kleinanzeigen
 +com.comuto
 +org.jellyfin.mobile
 +com.bandcamp.android
 +com.cubic.cumo.android.kvv
 +com.moovel.kvv
 +com.supercell.boombeach
 +com.wahoofitness.boltcompanion
 +io.voiapp.voi
 +de.sdvrz.ihb.mobile.secureapp.sparda.produktion
 +com.valvesoftware.android.steam.community
 +com.aspiro.tidal
 +com.google.android.inputmethod.latin
 +deezer.android.app
 +org.mozilla.firefox
 +com.myunibo
 +de.thomastreyer.beonbike
 +de.gls.pure
 +de.gls.pure
 +org.lichess.mobileapp
 +com.zhiliaoapp.musically
 +com.lynxspa.prontotreno
 +</file>
 +<file - /etc/systemd/system/gplaycli.service> 
 +[Unit]
 +Description=Gplaycli automatic APK mirror
 +After=network-online.target 
 +
 +[Service]
 +Type=simple
 +User=onny
 +ExecStart=/usr/bin/sh -c "rm -f /home/onny/.cache/gplaycli/token && /usr/bin/gplaycli -v -dc shamu --file /home/onny/.config/gplaycli/apk.list --folder /home/onny/www/fdroid/repo/ -c /home/onny/.config/gplaycli/gplaycli.conf && cd /home/onny/www/fdroid && env ANDROID_HOME=/opt/android-sdk fdroid update --create-metadata"
 +TimeoutStopSec=180
 +KillMode=process
 +KillSignal=SIGINT
 +
 +[Install]
 +WantedBy=multi-user.target
 +</file>
 +<file - /etc/systemd/system/gplaycli.timer>
 +[Unit]
 +Description=Gplaycli automatic APK mirror
 +
 +[Timer]
 +OnBootSec=5min
 +OnUnitActiveSec=12h
 +Unit=gplaycli.service
 +
 +[Install]
 +WantedBy=multi-user.target
 +</file>
 +<code bash>
 +systemctl daemon-reload
 +systemctl --now enable gplaycli.timer
 +</code>
 +Notes:
 +  * Manually put Threema apk into repo folder
 +===== public hosting =====
 +Create user for hosting site
 +<code bash>
 +useradd -m example
 +mkdir /home/example/www
 +ln -s /home/example/www /var/www/example.de
 +chmod +x /home/example
 +</code>
 +Copy php-fpm profile
 +<code bash>
 +cp /etc/php/php-fpm.d/sexypump.de.conf /etc/php/php-fpm.d/example.com
 +</code>
 +Replace all occurences from the domain (''sexypump.de'') and the user (''sexypump'') with your domain and user. Now restart ''php-fpm'':
 +<code bash>
 +systemctl restart php-fpm
 +</code>
 +Create nginx webserver configuration:
 +<file - /etc/nginx/sites-available/example.de>
 +server {
 +    server_name example.de www.example.de;
 +    access_log /var/log/nginx/example.de.access.log;
 +    error_log /var/log/nginx/example.de.error.log;
 +    root /var/www/example.de/wordpress/;
 +
 +    location / {
 +        index index.php index.htm index.html;
 +    }
 +
 +    location ~ \.php$ {
 +        include fastcgi_params;
 +        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
 +        fastcgi_pass unix:/var/run/php-fpm/example.de_php.sock;
 +        fastcgi_index index.php;
 +        #fastcgi_split_path_info ^(.+\.php)(/.+)$;
 +        fastcgi_intercept_errors on;
 +    }
 +}
 +</file>
 +Enable webserver configuration:
 +<code bash>
 +ln -s /etc/nginx/sites-available/example.de /etc/nginx/sites-enabled/
 +systemctl restart nginx
 +</code>
 +Enable SSL caddy proxy on ''http.pi''. Edit as user ''caddy'' and append following part:
 +<file - /opt/caddy/Caddyfile>
 +www.example.de example.de {
 +        log /var/log/caddy/example.de_access.log
 +        gzip
 +        tls crux@project-insanity.org
 +        proxy / http://http-pub.pi:80 {
 +                header_upstream Host {host}
 +                header_upstream X-Real-IP {remote}
 +                header_upstream X-Forwarded-Proto {scheme}
 +                header_downstream -Server ""
 +        }      
 +
 +</file>
 +Restart caddy process after that. Depending on the permissions of your webroot, you can run:
 +<code bash>
 +sudo gpasswd -a example http
 +</code>
 +Mysql database creation on ''mysql.pi'':
 +<code sql>
 +CREATE DATABASE IF NOT EXISTS sexypump;
 +GRANT ALL PRIVILEGES ON sexypump.* TO 'sexypump'@'http-pub' IDENTIFIED BY '****';
 +FLUSH PRIVILEGES;
 +</code>
 +<file - /etc/conf.d/ballisticc.de.ini>
 +upload_max_filesize = 1000M
 +post_max_size = 1000M
 +</file>
 +===== podcast feeds =====
 +<code bash>
 +sudo cp /home/onny/www/laboumdeluxe/laboumdeluxe_* /etc/systemd/system/
 +sudo cp /home/onny/www/bounce/bounce_* /etc/systemd/system/
 +systemctl enable --now bounce_feed.timer laboumdeluxe_feed.timer kampus_hakatze_feed.timer
 +
 +</code>