Site Tools


New release candidate available: 2020-06-01 "Hogfather". upgrade now! [51] (what's this?)
projectinsanity:server_setup

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::2 5.5TB pending (picloud)
http 10.25.0.100 2a01:4f8:191:327::10 1TB 05.02.20 (picloud)
http-pub 10.25.0.101 2a01:4f8:191:327::11 500G 05.02.20 (picloud)
mail 10.25.0.102 2a01:4f8:191:327::12 500G 07.01.20 (picloud)
mysql 10.25.0.103 2a01:4f8:191:327::13 100G 06.01.20 (picloud)
playground 10.25.0.104 2a01:4f8:191:327::14 500G 06.01.20 (picloud)
storage 10.25.0.105 2a01:4f8:191:327::15 1TB 07.01.20 (picloud)

Setup

  • IPv4: 144.76.16.40
  • IPv6: 2a01:4f8:191:327::2

Im Rescue system:

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

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:

/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
/etc/systemd/networkd/25-bridge.netdev
[NetDev]
Name=br-internal
Kind=bridge
/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

core system

pacman -S mosh tmux htop dmidecode fail2ban openvpn qemu openbsd-netcat openssh easy-rsa fish
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

dnsmasq settings, ready to listen on wireguard subnet

/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

systemd resolved dns resolver settings

/etc/systemd/resolved.conf
[...]
[resolve]
DNSStubListener=no
/etc/systemd/resolved.conf.d/dns_over_tls.conf
[Resolve]
DNSOverTLS=opportunistic
/etc/systemd/resolved.conf.d/dnssec.conf
[Resolve]
DNSSEC=true
/etc/systemd/resolved.conf.d/dns_servers.conf
[Resolve]
DNS=2620:fe::fe 9.9.9.9
/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

custom pi archlinux repo

/etc/pacman.conf
...
[projectinsanity]
SigLevel = PackageOptional
Server = https://onny.project-insanity.org/archlinux

archlinux auto update

/etc/pacman.conf
...
[projectinsanity]
SigLevel = PackageOptional
Server = https://onny.project-insanity.org/archlinux
/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
/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
systemctl enable --now autoupdate.timer

nftables

nftables firewall & routing

/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;
		#oif {"enp3s0","br-internal"} masquerade
		ip saddr 10.25.0.1/24 oifname {"enp3s0", "br-internal"} masquerade
	}
}
nftables.service.d/overwrite.conf
[Unit]
Wants=
Wants=libvirtd.service
Before=
After=libvirtd.service
pacman -S nftables
systemctl enable --now nftables

libvirtd

libvirt network configuration 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>

libvirt qemu hook

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

wireguard

pacman -S wireguard-arch
mkdir /etc/wireguard
cd /etc/wireguard
wg genkey | tee privatekey | wg pubkey > publickey
chmod 600 privatekey
chown root:root privatekey
/etc/systemd/network/99-server.netdev
[NetDev]
Name = wg0
Kind = wireguard
Description = Wireguard

[WireGuard]
ListenPort = 51820
PrivateKey = [SERVER PRIVATE KEY]

[WireGuardPeer]
# onny 10.25.40.2
PublicKey = [ONNY's PUBLIC KEY]
AllowedIPs = 10.25.40.0/24
# st-think 10.25.40.3
PublicKey = [ST-THINK's PUBLIC KEY]
AllowedIPs = 10.25.40.0/24
# neutrino 10.25.40.4
PublicKey = [NEUTRINO's PUBLIC KEY]
AllowedIPs = 10.25.40.0/24
# arne 10.25.40.5
PublicKey = [ARNE's PUBLIC KEY]
AllowedIPs = 10.25.40.0/24
# st-rpi-gravograf 10.25.40.6
PublicKey = [ST-RPI-GRAVOGRAF PUBLIC KEY]
AllowedIPs = 10.25.40.0/24
# st-rpi-home 10.25.40.7
PublicKey = [ST-RPI-HOME PUBLIC KEY]
AllowedIPs = 10.25.40.0/24
# st-1 10.25.40.8
PublicKey = [ST-1 PUBLIC KEY]
AllowedIPs = 10.25.40.0/24
# st-2 10.25.40.9
PublicKey = [ST-2 PUBLIC KEY]
AllowedIPs = 10.25.40.0/24
/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

client

pacman -S wireguard-arch
mkdir /etc/wireguard
cd /etc/wireguard
wg genkey | tee privatekey | wg pubkey > publickey
chmod 600 privatekey
chown root:root privatekey
/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
/etc/systemd/network/99-client.network
[Match]
Name = wg0

[Network]
Address = 10.25.40.2/32
systemctl restart systemd-networkd

systemd-journal logging server

/etc/systemd/journal-remote.conf
[Remote]
SplitMode=host
/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
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

ArchLinux Gastsystem

Erstellen

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

Löschen

virsh destroy http
virsh undefine http
lvremove /dev/vg0/http

Speicher vergrößern

virsh shutdown http
lvresize -L +20G vg0/http
virsh start http

Auf dem Gastsystem ausführen:

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 /

Bei neueren Version von libguestfs-tools (>1.16.34) könnte man auch die Partitionstabelle und Dateisystem von dem Host aus resizen und müsste dafür nicht das Gastsystem neustarten.

Backup

Raw backup logical volume to picloud (homeserver onnuex)

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

Recover backup

gpg -o /mnt/playground.img -d /mnt/playground.img.gpg

Unfinished backup script:

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

Einrichten

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
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

nftables

/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;
        }
}

systemd-networkd

/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

pacman

project-insanity build server repo

/etc/pacman.conf
[...]

[projectinsanity]
SigLevel = PackageOptional
Server = https://onny.project-insanity.org/archlinux

archlinux auto update

/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
/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
systemctl enable --now autoupdate.timer

systemd-journald

systemd logging upload

/etc/systemd/journal-upload.conf
[Upload]
URL=http://10.25.0.1:19532
/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
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

mail.pi

on mail.pi

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

on

/etc/maddy/maddy.conf
...
$(hostname) = turbotux.de
...
$(primary_domain) = turbotux.de
...
tls /etc/maddy/certs/$(hostname)/fullchain.pem /etc/maddy/certs/$(hostname)/privkey.pem
...
maddyctl users create postmaster
maddyctl users create onny@turbotux.de

turbotux.de dns record. get dkim key in /var/lib/maddy/dkim-keys/turbotux.de-default.dns

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="

forwarding/nat on host.pi

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

tls. on mail.pi

chmod +x /var/lib/private
sudo -u maddy ssh-keygen # all default values
cat /var/lib/maddy/.ssh/id_rsa.pub

on http.pi

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 :(

mysql.pi

mariadb

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
/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"
chmod 600 /etc/pacman.d/hooks/40-mariadb.hook

postgresql

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
/var/lib/postgres/data/postgresql.conf
[...]
listen_addresses = '*'
[...]
/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
/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

http.pi

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
/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

custom caddy installation

pacaur -d caddy
~/.cache/pacaur/caddy/PKGBUILD
[...]
#    'http.hugo'
    'http.ipfilter'
#    'http.jekyll'
[...]
cd ~/.cache/pacaur/caddy
makepkg -i --skipinteg
/etc/systemd/system/caddy.service.d/override.conf
[Service]
ProtectHome=false

caddy

/etc/caddy/conf.d/archbox.icu.conf
www.archbox.icu archbox.icu {
        log /var/log/caddy/archbox.icu_access.log
        gzip
        tls onny@project-insanity.org
        proxy / http://playground.pi {
                websocket
        }      
} 
/etc/caddy/conf.d/ausstellung-virtuell.de.conf
www.ausstellung-virtuell.de ausstellung-virtuell.de {
        log /var/log/caddy/ausstellung-virtuell.de_access.log
        gzip
        tls onny@project-insanity.org
        proxy / http://http-pub.pi {
                transparent
        }
} 
/etc/caddy/conf.d/ausstellung-virtuell.de.conf
www.xn--bioldle-8wa.de xn--bioldle-8wa.de {
        log /var/log/caddy/biolädle.de_access.log
        gzip
        tls onny@project-insanity.org
        proxy / http://http-pub.pi {
                transparent
        }      
} 
/etc/caddy/conf.d/blog.project-insanity.org.conf
blog.project-insanity.org/106fm {
        log /var/log/caddy/project-insanity.org_access.log
        errors /var/log/caddy/project-insanity.org_errors.log

        gzip
        tls onny@project-insanity.org

        header / {
                Content-Type "application/ogg"
        }

        proxy / http://storage.pi:8080 {
                transparent
        }      
}

blog.project-insanity.org {
        log /var/log/caddy/project-insanity.org_access.log
        gzip
        tls onny@project-insanity.org

        root /usr/share/webapps/wordpress
        fastcgi / /var/run/php-fpm/php-fpm.sock php {
                read_timeout 1000s
                send_timeout 1000s
        }

        rewrite {
                if {path} not_match ^\/wp-admin
                to {path} {path}/ /index.php?{query}
        }
}
/etc/caddy/conf.d/einfach-abhängen.de.conf
xn--einfach-abhngen-blb.de www.xn--einfach-abhngen-blb.de {
        log /var/log/caddy/einfach-abhängen.de_access.log
        gzip
        tls onny@project-insanity.org
        proxy / http://http-pub.pi {
                transparent
        }      
} 
/etc/caddy/conf.d/git.project-insanity.org.conf
git.project-insanity.org {
    log /var/log/caddy/git.project-insanity.org_access.log
    errors /var/log/caddy/git.project-insanity.org_errors.log

    rewrite {
        if_op or

        if {>User-Agent} has SemrushBot
        if {>User-Agent} has MJ12Bot
        if {>User-Agent} has DotBot
        if {>User-Agent} has AhrefsBot

        to /bad-robot
    }

    status 403 /bad-robot

    proxy / unix:/run/gitlab/gitlab-workhorse.socket {
        fail_timeout 300s
        max_fails 100
        transparent
    }
}
/etc/caddy/conf.d/http.pi.conf
http://http.pi {
        log /var/log/caddy/http.pi_access.log
        errors /var/log/caddy/http.pi_errors.log
        gzip

        tls off
        root /var/www
        browse

        fastcgi / /var/run/php-fpm/http.pi_php-fpm.sock php {
                index index.php index.htm index.html
        }

        #ipfilter / {
        #       rule allow
        #       ip 10.25.0.0/24 2a01:4f8:191:327::/64
        #}
}
/etc/caddy/conf.d/jhartung.sinewell.de.conf
jhartung.sinewell.de {
    log /var/log/caddy/jhartung.sinewell.de_access.log
    errors /var/log/caddy/jhartung.sinewell.de_errors.log
    gzip
    tls onny@project-insanity.org
    proxy / https://****.myfritz.net:46190
}
/etc/caddy/conf.d/lit-eratur.de.conf
www.lit-eratur.de lit-eratur.de {
        log /var/log/caddy/lit-eratur.de_access.log
        gzip
        tls onny@project-insanity.org
        proxy / http://http-pub.pi {
                transparent
        }      
} 
/etc/caddy/conf.d/music-id.xyz.conf
www.music-id.xyz music-id.xyz {
        log /var/log/caddy/music-id.xyz_access.log
        errors /var/log/caddy/music-id.xyz_errors.log
        gzip
        tls onny@project-insanity.org
        proxy / http://playground.pi:8080 {
                transparent
        }      
} 
/etc/caddy/conf.d/nextcloud.project-insanity.org.conf
nextcloud.project-insanity.org {

        root   /usr/share/webapps/nextcloud
        log    /var/log/caddy/nextcloud.project-insanity.org_access.log
        errors /var/log/caddy/nextcloud.project-insanity.org_errors.log

        tls onny@project-insanity.org {
                curves X25519 p256 p384 p521
        }

        fastcgi / /var/run/php-fpm/php-fpm.sock php {
                env PATH /bin
        }

        header / {
                 Strict-Transport-Security         "max-age=15768000;"
        }

        # checks for images
        rewrite {
                ext .svg .gif .png .html .ttf .woff .ico .jpg .jpeg
                r ^/index.php/(.+)$
                to /{1} /index.php?{1}
        }

        rewrite {
                r ^/\.well-known/host-meta$
                to /public.php?service=host-meta&{query}
        }
        rewrite {
                r ^/\.well-known/host-meta\.json$
                to /public.php?service=host-meta-json&{query}
        }
        rewrite {
                r ^/\.well-known/webfinger$
                to /public.php?service=webfinger&{query}
        }

        rewrite {
                r ^/index.php/.*$
                to /index.php?{query}
        }

        # client support (e.g. os x calendar / contacts)
        redir /.well-known/carddav /remote.php/carddav 301
        redir /.well-known/caldav /remote.php/caldav 301

        # remove trailing / as it causes errors with php-fpm
        rewrite {
                r ^/remote.php/(webdav|caldav|carddav|dav)(\/?)(\/?)$
                to /remote.php/{1}
        }

        rewrite {
                r ^/remote.php/(webdav|caldav|carddav|dav)/(.+?)(\/?)(\/?)$
                to /remote.php/{1}/{2}
        }

        rewrite {
                r ^/public.php/(dav|webdav|caldav|carddav)(\/?)(\/?)$
                to /public.php/{1}
        }

        rewrite {
                r ^/public.php/(dav|webdav|caldav|carddav)/(.+)(\/?)(\/?)$
                to /public.php/{1}/{2}
        }

        # .htaccess / data / config / ... shouldn't be accessible from outside
        status 403 {
                /.htaccess
                /data
                /config
                /db_structure
                /.xml
                /README
        }

}
/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
        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
    }
}
/etc/caddy/conf.d/onny.project-insanity.org.conf
onny.project-insanity.org {
        log /var/log/caddy/onny.project-insanity.org_access.log
        gzip
        tls onny@project-insanity.org
        proxy / http://http-pub.pi {
                websocket
                transparent
        }
} 
/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
    }
}
/etc/caddy/conf.d/wiki.project-insanity.org.conf
wiki.project-insanity.org {
        log /var/log/caddy/wiki.project-insanity.org_access.log
        root /usr/share/webapps/dokuwiki
        gzip
        tls onny@project-insanity.org

        fastcgi / /var/run/php-fpm/php-fpm.sock php {
          index doku.php
        }

        internal /forbidden

        rewrite {
          r /(data/|conf/|bin/|inc/|install.php)
          to /forbidden
        }
        rewrite /_media {
          to /lib/exe/fetch.php?media={path}&{query}
        }
        rewrite /_detail {
          to /lib/exe/detail.php?media={path}&{query}
        }
        rewrite /_export {
          r /([^/]+)/(.*)
          to /doku.php?do=export_{1}&id={2}
        }
        rewrite {
          if {path} not_match /lib/.*
          if {path} not_match /forbidden
          r /(.*)
          to {uri} /doku.php?id={1}&{query}
        }
}
/etc/caddy/conf.d/zirkel.fun.conf
nextcloud.zirkel.fun {

        root   /usr/share/webapps/nextcloud
        log /var/log/caddy/nextcloud.sexypump.de_access.log
        errors /var/log/caddy/nextcloud.sexypump.de_errors.log

        fastcgi / /var/run/php-fpm/php-fpm.sock php {
          env PATH /bin
        }

        # checks for images
        rewrite {
                ext .svg .gif .png .html .ttf .woff .ico .jpg .jpeg
                r ^/index.php/(.+)$
                to /{1} /index.php?{1}
        }

        rewrite {
                r ^/index.php/.*$
                to /index.php?{query}
        }

        # client support (e.g. os x calendar / contacts)
        redir /.well-known/carddav /remote.php/carddav 301
        redir /.well-known/caldav /remote.php/caldav 301

        # remove trailing / as it causes errors with php-fpm
        rewrite {
                r ^/remote.php/(webdav|caldav|carddav|dav)(\/?)(\/?)$
                to /remote.php/{1}
        }

        rewrite {
                r ^/remote.php/(webdav|caldav|carddav|dav)/(.+?)(\/?)(\/?)$
                to /remote.php/{1}/{2}
        }

        rewrite {
                r ^/public.php/(dav|webdav|caldav|carddav)(\/?)(\/?)$
                to /public.php/{1}
        }

        rewrite {
                r ^/public.php/(dav|webdav|caldav|carddav)/(.+)(\/?)(\/?)$
                to /public.php/{1}/{2}
        }

        # .htaccess / data / config / ... shouldn't be accessible from outside
        status 403 {
                /.htaccess
                /data
                /config
                /db_structure
                /.xml
                /README
        }

        header / Strict-Transport-Security "max-age=31536000;"

}

www.zirkel.fun zirkel.fun {
        log /var/log/caddy/zirkel.fun_access.log
        gzip
        tls onny@project-insanity.org
        proxy / http://http-pub.pi {
                transparent
        }      
} 

php-fpm

cp /etc/php/php-fpm.d/www.conf /etc/php/php-fpm.d/http.pi.conf
/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
[...]
/etc/php/php-fpm.d/http.pi.conf
[...]
[http.pi]
[...]
listen = /run/php-fpm/http.pi_php-fpm.sock
[...]

wordpress

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 wordpress-plugin-wp-statistics wordpress-plugin-co-authors-plus wordpress-theme-geist wordpress-plugin-wp-user-avatar
chown -R http:http /usr/share/webapps/wordpress/wp-admin /usr/share/webapps/wordpress/wp-includes
/etc/php/conf.d/wordpress.ini
extension=mysqli
/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 );
/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-core wp-statistics co-authors-plus wp-user-avatar'"
sudo -u http wp plugin activate --path=/usr/share/webapps/wordpress antispam-bee code-syntax-block jetpack jetpack-lite lightbox-photoswipe wp-gdpr-core wp-statistics co-authors-plus wp-user-avatar
sudo -u http wp theme activate --path=/usr/share/webapps/wordpress geist

Additional CSS for Geist theme

@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;
	}

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

Additional CSS for Ghost theme:

@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;
}

co-authors-plus plugin

template-Anpassung
How to Add Multiple Authors (Co-Authors) for Posts in WordPress

/home/pi_wordpress/wordpress/functions-content.php
if ( function_exists( 'coauthors_posts_links' ) ) {
    coauthors_posts_links();
} else {
    the_author_posts_link();
}

invoiceninja

on mysql.pi

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;

on http.pi

pacman -S invoiceninja
/etc/php/conf.d/composer.ini
extension=gmp
cd /usr/share/webapps/invoiceninja
sudo chown -R http:http storage public/logo bootstrap
sudo chown http:http .
sudo -u http composer install
/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
        }
}
[...]

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

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

Visit installation wizard at http://http.pi/invoiceplane/index.php/setup

/usr/share/webapps/invoiceplane/ipconfig.php
[...]
SETUP_COMPLETED=true
DB_HOSTNAME=mysql.pi
DB_USERNAME=invoiceplane
DB_PASSWORD=****
DB_DATABASE=invoiceplane
DISABLE_SETUP=true

firefox account server

pacaur -S mozilla-firefox-account-server

podcasttune

not yet stable

dokuwiki

/etc/webapps/dokuwiki/local.php
<?php
$conf['title'] = 'Project-Insanity';
$conf['userewrite']  = 1;

dw2pdf plugin

wget "https://github.com/splitbrain/dokuwiki-plugin-dw2pdf/tarball/master" -O /tmp/dw2pdf.tar.gz
cd /tmp
tar xvf dw2pdf.tar.gz
mv splitbrain* /var/lib/dokuwiki/plugins/dw2pdf
/usr/lib/dokuwiki/plugins/dw2pdf/conf/default.php
[...]
$conf['doublesided']      = 0;
[...]
/usr/lib/dokuwiki/plugins/dw2pdf/tpl/default/style.css
@page {
    margin-left: 100px;
}

[...]

usage: https://wiki.project-insanity.org/onny?do=export_pdf

  • Todo
    • DSGVO complience

gitlab

pacman -S yarn sendmail gitlab

disable backups

/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/)

configure database connection

/etc/webapps/gitlab/database.yml
production:
  adapter: postgresql
  encoding: unicode
  database: gitlabhq_production
  pool: 10
  username: gitlab
  password: "****"
  host: mysql.pi

on mysql.pi

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;"

on http.pi

 cd /usr/share/webapps/gitlab
 sudo -u gitlab -H bundle-2.5 exec rake assets:precompile RAILS_ENV=production
 sudo -u gitlab -H bundle-2.5 exec rake gitlab:setup RAILS_ENV=production
 systemctl enable --now gitlab-workhorse redis gitlab-unicorn gitlab-sidekiq gitlab-gitaly

Enable smtp, mail delivery

/usr/share/webapps/gitlab/config/initializers/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

further general mail settings

/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: ''

Auto migrate on pacman update

/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-unicorn gitlab-sidekiq gitlab-gitaly && /usr/bin/sudo -u gitlab /usr/bin/bash -c 'cd /usr/share/webapps/gitlab; EXECJS_RUNTIME=Disabled bundle-2.5 exec rake db:migrate RAILS_ENV=production'"
/etc/webapps/gitlab/secrets.yml
****
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

misc settings:

onlyoffice documentserver

pacman -S npm nodejs rabbitmq redis onlyoffice-documentserver
ln -s /usr/share/libalpm/hooks/onlyoffice-documentserver.hook /etc/pacman.d/hooks/

on mysql.pi

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
/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
    }
}
/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"
                }
        }
/etc/hosts
10.25.0.100 nextcloud.project-insanity.org
systemctl enable --now rabbitmq redis onlyoffice-docservice onlyoffice-fileconverter onlyoffice-spellchecker

officepad

/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
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
/usr/share/webapps/officepad/config/default.json
[...]
siteUrl": "https://bwsas-prod-oo-02.lsdf.kit.edu/"
[...]

nextcloud

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-radio nextcloud-app-deck nextcloud-app-onlyoffice nextcloud-app-bookmarks nextcloud-app-notes nextcloud-app-talk
/etc/php/php-fpm.d/www.conf
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp

php performance optimizations

/etc/php/conf.d/nextcloud.ini
memory_limit = 512M

extension=gd
extension=pdo_mysql
extension=apcu
extension=intl
extension=iconv
extension=imagick

# 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
/usr/share/webapps/nextcloud/conf/config.php
<?php
$CONFIG = array (
  'instanceid' => '****',
  'passwordsalt' => '****',
  'datadirectory' => '/usr/share/webapps/nextcloud/data',
  'dbtype' => 'mysql',
  'version' => '13.0.2.1',
  'dbname' => 'nextcloud',
  'dbhost' => 'mysql.pi',
  'dbtableprefix' => 'oc_',
  'mysql.utf8mb4' => true,
  'dbuser' => 'nextcloud',
  'dbpassword' => '****',
  'installed' => true,
  'theme' => '',
  'maintenance' => false,
  'loglevel' => 2,
  'cron_log' => true,
  'maxZipInputSize' => 5145728000,
  'allowZipDownload' => true,
  'memcache.local' => '\\OC\\Memcache\\APCu',
  'trusted_domains' => 
  array (
    0 => 'nextcloud.project-insanity.org',
    1 => 'http-new.pi',
    2 => 'office.project-insanity.org',
    3 => 'onny.project-insanity.org',
  ),
  'secret' => '****',
  'mail_domain' => 'project-insanity.org',
  'mail_smtpmode' => 'php',
  'mail_from_address' => 'nextcloud',
  'trashbin_retention_obligation' => 'auto',
  'overwrite.cli.url' => 'https://nextcloud.project-insanity.org',
  'htaccess.RewriteBase' => '/',
);

Due to packaging bug and hardened php-fpm.service file, an unit file overwrite is required:

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

Auto upgrade on pacman update

/etc/pacman.d/hooks/nextcloud.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/runuser -u http -- /usr/bin/php /usr/share/webapps/nextcloud/occ upgrade

Nextcloud background job (cron)

[Unit]
Description=Nextcloud cron.php job
 
[Service]
User=http
ExecStart=/usr/bin/php -f /usr/share/webapps/nextcloud/cron.php
 
[Install]
WantedBy=basic.target
/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
systemctl enable --now nextcloudcron.timer

Add additional mimetype for keeweb app

cd /usr/share/webapps/nextcloud
cp resources/config/mimetypemapping.dist.json config/mimetypemapping.json

add kdbx line to json config

/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"],
[...]
sudo -u http /usr/share/webapps/nextcloud/occ app:enable twofactor_gateway audioplayer polls extract suspicious_login mail news calendar contacts keeweb radio deck onlyoffice bookmarks notes talk

mail

disable ssl verification of imap/smpt host

/usr/share/webapps/nextcloud/config/config.php
[...]
  'app.mail.verify-tls-peer' => false,
[...]

twofactor_gateway

disposible phone number registration http://www.getsmscode.com

/etc/webapps/signal-web-gateway/config.yml
[...]
tel: "+1774****"
[...]
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

activate 2FA in Settings → Security (User)

onlyoffice

mantainance

Run file integrity checks

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

phpmyadmin

/etc/webapps/phpmyadmin/config.inc.php
[...]
/* Server parameters */
$cfg['Servers'][$i]['host'] = 'mysql.pi';
$cfg['Servers'][$i]['compress'] = false;
[...]

cockpit

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
/etc/sudoers
[...]
cockpit ALL=(ALL) ALL
[...]
/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

storage.pi

kol ha campus archive radio stream

pacman -S vlc pulseaudio
/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
/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
/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>
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

also added a caddy rule on http.pi for the url: https://blog.project-insanity.org/106fm

bitcoind

pacman -S bitcoin-daemon
systemctl start bitcoind
systemctl enable bitcoind
ufw allow from 10.25.0.0/24 to any port 8333

https://bitcoin.stackexchange.com/a/75312

playground.pi

pacman -S devtools

beta.saai.digital

pacman -S iptables-nft
/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
  }
}
systemctl enable --now docker

QuakeJS

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
/etc/conf.d/quakejs
QUAKEJS_DS_PARAMS="+set fs_cdn cdn.quake.turbotux.de +set fs_game baseq3 +set dedicated 1 +exec server.cfg"
/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
/etc/webapps/quakejs/web.json
{ 
        "content": "cdn.quake.turbotux.de",
        "port": 8081
}
systemctl enable --now quakejs-ds quakejs quakejs-cdn

PI ArchLinux Repository

build and install auruitls from source

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

configure custom repository

/etc/pacman.conf
[...]
Include = /etc/pacman.d/projectinsanity
/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
/etc/suders
[...]
aur ALL = NOPASSWD: SETENV: /usr/bin/makechrootpkg
aur ALL = NOPASSWD: /usr/bin/arch-nspawn
[...]
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
/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
/usr/bin/pi-archlinuxrepo-update.sh
#!/bin/bash
for package in $(pacman -Sql projectinsanity) 
do
  aur sync --no-view -c $package
done
/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
systemctl enable --now aurupdate.timer
sudo -u aur aur sync -d projectinsanity -c waterfox-current-bin wl-clipboard-git pkgbuild-introspection networkmanager-iwd tor-browser-en r128gain split2flac id3ted redshift-wlr-gamma-control-git krop wcalc anbox-git ocenaudio-bin smloadr soulseekqt brave-bin aurutils brightnessctl 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 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 ttf-font-awesome-4 zeronet teamviewer scrcpy ttyd python-django-rest-framework wdisplays-git wf-recorder-git dmenu-wayland-git python-soundcard python-soundfile pacaur archivemount micro python-rpi.gpio python-pad4pi python-pulse-control python-rplcd python-vlc plex-media-server python-mpv pmbootstrap wordpress-theme-geist linux-libre opensnitch-git powerpill osmctools tilemaker nextcloud-app-talk xerox-phaser-6000-6010
pacman -S caddy
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

caddy configuration

/etc/caddy/conf.d/onny.project-insanity.org.conf
http://onny.project-insanity.org/archlinux {

        log /var/log/caddy/onny.project-insnaity.org_access.log
        errors /var/log/caddy/onny.project-insanity.org_errors.log
        tls off
        gzip

        root /var/cache/pacman/projectinsanity
        browse
}
systemctl restart caddy

caddy configuration on http-pub.pi:

/etc/caddy/conf.d/onny.project-insanity.org.conf
[...]
    proxy /archlinux playground.pi {
        transparent
    }
[...]
systemctl restart caddy

http-pub.pi

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
/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

custom caddy installation

pacaur -d caddy
~/.cache/pacaur/caddy/PKGBUILD
[...]
#    'http.expires'
    'http.filemanager'
#    'http.filter'
[...]
cd ~/.cache/pacaur/caddy
makepkg -i --skipinteg

caddy

/etc/caddy/conf.d/ausstellung-virtuell.de.conf
http://ausstellung-virtuell.de {
    redir https://www.ausstellung-virtuell.de
}

http://www.ausstellung-virtuell.de {
    log /var/log/caddy/ausstellung-virtuell.de_access.log
    errors /var/log/caddy/ausstellung-virtuell.de_errors.log

    gzip

    root /var/www/ausstellung-virtuell.de

    rewrite {
        r ^/(.+)$
        to /{1} /index.php?page={1}
    }

    fastcgi / /var/run/php-fpm/ausstellung-virtuell.de_php-fpm.sock php {
        index index.php
    }
}
/etc/caddy/conf.d/biolädle.de.conf
http://biolädle.de http://www.biolädle.de http://www.xn--bioldle-8wa.de http://xn--bioldle-8wa.de {
    log /var/log/caddy/biolädle.de_access.log
    errors /var/log/caddy/biolädle.de_errors.log
    tls off
    gzip

    root /var/www/biolädle.de

    proxy /etiketten unix:/run/uwsgi/biolaedle-etiketten-generator.sock {
        transparent
    }
    proxy /lagerhaltung unix:/run/uwsgi/biolaedle-lagerhaltung.sock {
        transparent
    }

    rewrite {
        if {path} not_match ^\/etiketten
        if {path} not_match ^\/lagerhaltung
        if {path} not_match ^\/wp-admin
        to {path} {path}/ /index.php?{query}
    }

    fastcgi / /var/run/php-fpm/biolädle.de_php-fpm.sock php {
        env HTTPS 1
        index index.php
    }
}
/etc/caddy/conf.d/einfach-abhängen.de.conf
http://einfach-abhängen.de http://www.einfach-abhängen.de http://xn--einfach-abhngen-blb.de http://www.xn--einfach-abhngen-blb.de {
    log /var/log/caddy/einfach-abhängen.de_access.log
    errors /var/log/caddy/einfach-abhängen.de_errors.log
    tls off
    gzip

    root /var/www/einfach-abhängen.de

    rewrite {
        if {path} not_match ^\/wp-admin
        to {path} {path}/ /index.php?{query}
    }

    fastcgi / /var/run/php-fpm/einfach-abhängen.de_php-fpm.sock php {
        env HTTPS 1
        index index.php
    }

}
/etc/caddy/conf.d/lit-eratur.de.conf
http://lit-eratur.de http://www.lit-eratur.de {
    log /var/log/caddy/lit-eratur.de_access.log
    errors /var/log/caddy/lit-eratur.de_errors.log
    tls off
    gzip

    root /var/www/lit-eratur.de

    proxy / unix:/run/uwsgi/literatur.sock {
        transparent
    }
}
/etc/caddy/conf.d/onny.project-insanity.org.conf
http://onny.project-insanity.org/arch-upstream/ {
    log /var/log/caddy/onny.project-insanity.org_access.log
    errors /var/log/caddy/onny.project-insanity.org_errors.log
    tls off
    gzip

    index index.html index.htm upstream.html

    root /usr/share/webapps/arch-upstream
}

http://onny.project-insanity.org {
    log /var/log/caddy/onny.project-insanity.org_access.log
    errors /var/log/caddy/onny.project-insanity.org_errors.log
    tls off
    gzip

    index index.html index.htm upstream.html

    fastcgi / /var/run/php-fpm/onny.project-insanity.org_php-fpm.sock php {
        index index.php
    }

    redir /arch-upstream /arch-upstream/
    
    root /var/www/onny.project-insanity.org

    header /files/kampus_hakatze.xml {
        Content-Type "application/rss+xml; charset=utf-8"
    }

    header /bounce/feed.xml {
        Content-Type "application/rss+xml; charset=utf-8"
    }

    header /laboumdeluxe/feed.xml {
        Content-Type "application/rss+xml; charset=utf-8"
    }

    header /getmetadata {
        Access-Control-Allow-Origin  *
    }

    proxy /getmetadata unix:/run/uwsgi/getmetadata.sock {
        transparent
    }
    proxy /feeds unix:/run/uwsgi/feeds.sock {
        transparent
    }
    proxy /pishare unix:/run/uwsgi/pishare.sock {
        transparent
    }
}
/etc/caddy/conf.d/zirkel.fun.conf
http://retro.zirkel.fun {
    log /var/log/caddy/zirkel.fun_access.log
    errors /var/log/caddy/zirkel.fun_errors.log
    tls off
    gzip

    root /var/www/zirkel.fun/retro
}

http://zirkel.fun http://www.zirkel.fun {
    log /var/log/caddy/zirkel.fun_access.log
    errors /var/log/caddy/zirkel.fun_errors.log
    tls off
    gzip

    root /var/www/zirkel.fun/root

    rewrite {
        if {path} not_match ^\/wp-admin
        to {path} {path}/ /index.php?{query}
    }
    
    fastcgi / /var/run/php-fpm/zirkel.fun_php-fpm.sock php {
        env HTTPS 1
    }
}
/etc/systemd/system/caddy.service.d/overwride.conf
[Service]
ProtectHome=false
LimitNOFILE=infinity
LimitNPROC=infinity
systemctl daemon-reload
systemctl restart caddy

Overwrite php-fpm.service configuration, allow access to home directories:

php-fpm.service.d/overwrite.conf
[Service]
ProtectHome=false

wordpress

/etc/php/conf.d/wordpress.ini
extension=mysqli

upload_max_filesize = 64M
post_max_size = 64M

uwsgi

pacman -S uwsgi-plugin-python python-bottle
mkdir /etc/uwsgi/systemd
/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
/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

getmetadata

pacman -S python-requests
/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
/etc/uwsgi/systemd/getmetadata.conf
rw_directory="/usr/share/webapps/getmetadata"
systemctl enable uwsgi-private@getmetadata
systemctl start uwsgi-private@getmetadata

biolaedle-etiketten-generator

pacman -S python-pandas python-reportlab python-xlrd python-bottle
/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
systemctl enable --now uwsgi@biolaedle\\x2detiketten\\x2dgenerator

feeds

pacman -S python-feedparser python-beautifulsoup4 python-pyrss2gen python-dateutil python-lxml
/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
/etc/uwsgi/systemd/feeds.conf
rw_directory="/usr/share/webapps/feeds"
systemctl enable uwsgi-private@feeds
systemctl start uwsgi-private@feeds

pishare

pacman -S nodejs
/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
systenmctl enable --now uwsgi@pishare

arch-upstream

pacman -S python-progressbar python-jinja
ln -s /usr/share/webapps/arch-upstream /var/www/onny.sexypump.de/
/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
/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
systemctl enable arch-upstream.timer
systemctl start arch-upstream.timer

fdroid repo gplay mirror

http-pub.pi

enable multilib

/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.
[...]
pacman -S fdroidserver android-sdk android-sdk-build-tools gplaycli
cd www
mkdir fdroid
cd fdroid
env ANDROID_HOME=/opt/android-sdk fdroid init
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 :)"
[...]
env ANDROID_HOME=/opt/android-sdk fdroid update --create-metadata
mkdir ~/.config/gplaycli
~/.config/gplaycli/gplaycli.conf
[Credentials]
gmail_address=****@gmail.com
gmail_password=****
token=False
~/.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
/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/ && 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
/etc/systemd/system/gplaycli.timer
[Unit]
Description=Gplaycli automatic APK mirror

[Timer]
OnBootSec=5min
OnUnitActiveSec=12h
Unit=gplaycli.service

[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl --now enable gplaycli.timer

Notes:

  • Manually put Threema apk into repo folder

public hosting

Create user for hosting site

useradd -m example
mkdir /home/example/www
ln -s /home/example/www /var/www/example.de
chmod +x /home/example

Copy php-fpm profile

cp /etc/php/php-fpm.d/sexypump.de.conf /etc/php/php-fpm.d/example.com

Replace all occurences from the domain (sexypump.de) and the user (sexypump) with your domain and user. Now restart php-fpm:

systemctl restart php-fpm

Create nginx webserver configuration:

/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;
    }
}

Enable webserver configuration:

ln -s /etc/nginx/sites-available/example.de /etc/nginx/sites-enabled/
systemctl restart nginx

Enable SSL caddy proxy on http.pi. Edit as user caddy and append following part:

/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 ""
        }      
} 

Restart caddy process after that. Depending on the permissions of your webroot, you can run:

sudo gpasswd -a example http

Mysql database creation on mysql.pi:

CREATE DATABASE IF NOT EXISTS sexypump;
GRANT ALL PRIVILEGES ON sexypump.* TO 'sexypump'@'http-pub' IDENTIFIED BY '****';
FLUSH PRIVILEGES;
/etc/conf.d/ballisticc.de.ini
upload_max_filesize = 1000M
post_max_size = 1000M

podcast feeds

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
projectinsanity/server_setup.txt · Last modified: 2020/05/19 17:37 by 10.25.0.1