servers/psmf: add psmf server docs, nginx/tailscale config, and data-sync

Document the psmf host (DNS, second tailscale netns instance, nginx
vhosts, migration plan) and add the docker-dev-22 psmf-data-sync
service plus the storage-23 pg_hba.conf entry it needs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-09 00:05:39 +02:00
parent d541f2e1d2
commit 6efa069b12
18 changed files with 624 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
# Reverse proxy: horst-2 default site -> horst-1 Apache (10.0.0.5)
# Deployed during the horst-1 -> horst-2 migration.
# See servers/psmf/migration-plan.md.
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
# Long bodies / uploads from the legacy PHP intranet app.
client_max_body_size 64m;
location / {
proxy_pass http://10.0.0.5;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_connect_timeout 10s;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
}

View File

@@ -0,0 +1,27 @@
# Reverse proxy: psmf-new.intranet -> dockerized PHP intranet app on horst-2 (127.0.0.1:8080)
# See servers/psmf/migration-plan.md and servers/psmf/dns-configuration.md.
server {
listen 80;
listen [::]:80;
server_name psmf-new.intranet;
# Long bodies / uploads from the PHP intranet app.
client_max_body_size 64m;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_connect_timeout 10s;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
}

View File

@@ -0,0 +1,28 @@
# Reverse proxy: psmf.intranet -> horst-1 Apache (10.0.0.5)
# Same target as the default site, but bound to the psmf.intranet host header.
# See servers/psmf/migration-plan.md and servers/psmf/dns-configuration.md.
server {
listen 80;
listen [::]:80;
server_name psmf.intranet;
# Long bodies / uploads from the legacy PHP intranet app.
client_max_body_size 64m;
location / {
proxy_pass http://10.0.0.5;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_connect_timeout 10s;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
}

View File

@@ -0,0 +1,15 @@
services:
app:
image: gitea.home.hrajfrisbee.cz/psmf/psmf-intranet:1.03
ports:
- "8080:8080"
environment:
DB_HOST: ${DB_HOST:-host.docker.internal}
DB_NAME: ${DB_NAME:-psmf}
DB_USER: ${DB_USER:-psmf}
DB_PASS: ${DB_PASS:-psmf}
# PSMF_BASE_URL: http://127.0.0.1:8080 # override for PDF export when behind a proxy
PSMF_HEADER_TEXT: "Vítejte na intranetu PSMF (PHP {PHP_VERSION})"
PSMF_HEADER_BG: "#a0b000"
PSMF_SHOW_PHP_VERSION: "1"
restart: unless-stopped

View File

@@ -0,0 +1,21 @@
# location: /etc/systemd/system/tailscaled-ts2.service
[Unit]
Description=tailscaled in ts2 netns
After=ts2-netns.service network-online.target
Requires=ts2-netns.service
BindsTo=ts2-netns.service
[Service]
ExecStart=/usr/sbin/ip netns exec ts2 /usr/sbin/tailscaled \
--state=/var/lib/tailscale-ts2/tailscaled.state \
--socket=/run/tailscale-ts2/tailscaled.sock \
--port=41642 \
--tun=tailscale0
Restart=on-failure
RestartSec=5s
RuntimeDirectory=tailscale-ts2
StateDirectory=tailscale-ts2
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,11 @@
#!/usr/bin/env bash
# best-effort cleanup, don't fail on missing pieces
# location: /usr/local/sbin/ts2-netns-down
iptables -t nat -D POSTROUTING -s 10.200.0.0/30 -o br0 -j MASQUERADE 2>/dev/null || true
iptables -D FORWARD -i veth-ts2 -o br0 -j ACCEPT 2>/dev/null || true
iptables -D FORWARD -o veth-ts2 -i br0 -m state --state RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || true
ip link del veth-ts2 2>/dev/null || true
ip netns del ts2 2>/dev/null || true
rm -rf /etc/netns/ts2

View File

@@ -0,0 +1,55 @@
#!/usr/bin/env bash
# location: /usr/local/sbin/ts2-netns-up
set -e
# bail out clean if anything already exists from a previous run
ip netns list | grep -qw ts2 || ip netns add ts2
ip link show veth-ts2 &>/dev/null || \
ip link add veth-ts2 type veth peer name veth-ts2-ns
# move peer into ns only if it's still on the host
ip link show veth-ts2-ns &>/dev/null && \
ip link set veth-ts2-ns netns ts2
ip addr add 10.200.0.1/30 dev veth-ts2 2>/dev/null || true
ip link set veth-ts2 up
ip -n ts2 addr add 10.200.0.2/30 dev veth-ts2-ns 2>/dev/null || true
ip -n ts2 link set veth-ts2-ns up
ip -n ts2 link set lo up
ip -n ts2 route add default via 10.200.0.1 2>/dev/null || true
mkdir -p /etc/netns/ts2
echo "nameserver 1.1.1.1" > /etc/netns/ts2/resolv.conf
sysctl -wq net.ipv4.ip_forward=1
# -C checks if rule exists, -A appends only if missing
iptables -t nat -C POSTROUTING -s 10.200.0.0/30 -o br0 -j MASQUERADE 2>/dev/null || \
iptables -t nat -A POSTROUTING -s 10.200.0.0/30 -o br0 -j MASQUERADE
iptables -C FORWARD -i veth-ts2 -o br0 -j ACCEPT 2>/dev/null || \
iptables -A FORWARD -i veth-ts2 -o br0 -j ACCEPT
iptables -C FORWARD -o veth-ts2 -i br0 -m state --state RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || \
iptables -A FORWARD -o veth-ts2 -i br0 -m state --state RELATED,ESTABLISHED -j ACCEPT
# iptables rules + sysctl inside ts2 ns
# Forwarding inside ts2
ip netns exec ts2 sysctl -wq net.ipv4.ip_forward=1
# DNAT incoming ssh to host
ip netns exec ts2 iptables -t nat -C PREROUTING -i tailscale0 -p tcp --dport 22 -j DNAT --to-destination 10.200.0.1:22 2>/dev/null || \
ip netns exec ts2 iptables -t nat -A PREROUTING -i tailscale0 -p tcp --dport 22 -j DNAT --to-destination 10.200.0.1:22
# DNAT incoming http to host nginx
ip netns exec ts2 iptables -t nat -C PREROUTING -i tailscale0 -p tcp --dport 80 -j DNAT --to-destination 10.200.0.1:80 2>/dev/null || \
ip netns exec ts2 iptables -t nat -A PREROUTING -i tailscale0 -p tcp --dport 80 -j DNAT --to-destination 10.200.0.1:80
# DNAT incoming 8080 to docker web app in root ns
ip netns exec ts2 iptables -t nat -C PREROUTING -i tailscale0 -p tcp --dport 8080 -j DNAT --to-destination 10.200.0.1:8080 2>/dev/null || \
ip netns exec ts2 iptables -t nat -A PREROUTING -i tailscale0 -p tcp --dport 8080 -j DNAT --to-destination 10.200.0.1:8080
ip netns exec ts2 iptables -t nat -C POSTROUTING -o veth-ts2-ns -j MASQUERADE 2>/dev/null || \
ip netns exec ts2 iptables -t nat -A POSTROUTING -o veth-ts2-ns -j MASQUERADE

View File

@@ -0,0 +1,17 @@
# /etc/systemd/system/ts2-netns.service
[Unit]
Description=ts2 netns + veth + NAT
After=network-online.target
Wants=network-online.target
# tie tailscaled lifecycle to this
Before=tailscaled-ts2.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/sbin/ts2-netns-up
ExecStop=/usr/local/sbin/ts2-netns-down
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,2 @@
# location: /etc/netns/ts2/resolv.conf
nameserver 1.1.1.1