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:
157
servers/psmf/dns-configuration.md
Normal file
157
servers/psmf/dns-configuration.md
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
## disable systemd-resolved
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo mkdir -p /etc/systemd/resolved.conf.d
|
||||||
|
sudo tee /etc/systemd/resolved.conf.d/disable-stub.conf <<EOF
|
||||||
|
[Resolve]
|
||||||
|
DNSStubListener=no
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Fix /etc/resolv.conf symlink so the box itself still resolves
|
||||||
|
sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
|
||||||
|
|
||||||
|
sudo systemctl restart systemd-resolved
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## dnsmasq in ts2 namespace
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo mkdir -p /etc/dnsmasq-ts2
|
||||||
|
sudo tee /etc/dnsmasq-ts2/dnsmasq.conf <<'EOF'
|
||||||
|
# Inside ts2 netns — tailscale0 is the only real interface.
|
||||||
|
# Bind to all (namespace is isolated, so this is safe).
|
||||||
|
no-resolv
|
||||||
|
no-hosts
|
||||||
|
|
||||||
|
# Upstreams (explicit, no /etc/resolv.conf dependency inside netns)
|
||||||
|
server=1.1.1.1
|
||||||
|
server=9.9.9.9
|
||||||
|
|
||||||
|
# Zone
|
||||||
|
local=/intranet/
|
||||||
|
domain=intranet
|
||||||
|
|
||||||
|
address=/psmf.intranet/100.90.25.77
|
||||||
|
address=/psmf-new.intranet/100.90.25.77
|
||||||
|
|
||||||
|
cache-size=1000
|
||||||
|
log-facility=/var/log/dnsmasq-ts2.log
|
||||||
|
|
||||||
|
user=dnsmasq
|
||||||
|
pid-file=/run/dnsmasq-ts2.pid
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# systemd-unit
|
||||||
|
sudo tee /etc/systemd/system/dnsmasq-ts2.service <<'EOF'
|
||||||
|
[Unit]
|
||||||
|
Description=dnsmasq inside ts2 netns (intranet zone)
|
||||||
|
After=network-online.target
|
||||||
|
Wants=network-online.target
|
||||||
|
# If you have a unit that sets up the ts2 namespace + tailscaled inside it,
|
||||||
|
# add it here, e.g.:
|
||||||
|
# Requires=tailscaled-ts2.service
|
||||||
|
# After=tailscaled-ts2.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
NetworkNamespacePath=/var/run/netns/ts2
|
||||||
|
ExecStartPre=/usr/sbin/dnsmasq --test -C /etc/dnsmasq-ts2/dnsmasq.conf
|
||||||
|
ExecStart=/usr/sbin/dnsmasq -k -C /etc/dnsmasq-ts2/dnsmasq.conf
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# validate and start
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable --now dnsmasq-ts2
|
||||||
|
sudo systemctl status dnsmasq-ts2 --no-pager
|
||||||
|
|
||||||
|
|
||||||
|
sudo ip netns exec ts2 ss -lnup | grep :53
|
||||||
|
sudo ip netns exec ts2 dig @127.0.0.1 psmf.intranet +short
|
||||||
|
sudo ip netns exec ts2 dig @127.0.0.1 cloudflare.com +short
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## dnsmasq in root namespace
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo mkdir -p /etc/dnsmasq-root
|
||||||
|
sudo tee /etc/dnsmasq-root/dnsmasq.conf <<'EOF'
|
||||||
|
# Root netns instance. Stock dnsmasq.service must be disabled/masked
|
||||||
|
# so it doesn't fight us for port 53.
|
||||||
|
# systemd-resolved stub listener is disabled (see top of this file).
|
||||||
|
|
||||||
|
# Only listen on these — don't grab :53 on every interface.
|
||||||
|
bind-interfaces
|
||||||
|
interface=br0
|
||||||
|
interface=tailscale0
|
||||||
|
|
||||||
|
# Upstreams (explicit, no /etc/resolv.conf lookup)
|
||||||
|
no-resolv
|
||||||
|
no-hosts
|
||||||
|
server=1.1.1.1
|
||||||
|
server=9.9.9.9
|
||||||
|
|
||||||
|
# Zone
|
||||||
|
local=/intranet/
|
||||||
|
domain=intranet
|
||||||
|
|
||||||
|
address=/psmf.intranet/100.90.25.77
|
||||||
|
address=/psmf-new.intranet/100.90.25.77
|
||||||
|
|
||||||
|
cache-size=1000
|
||||||
|
log-facility=/var/log/dnsmasq-root.log
|
||||||
|
|
||||||
|
user=dnsmasq
|
||||||
|
pid-file=/run/dnsmasq-root.pid
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# systemd-unit
|
||||||
|
sudo tee /etc/systemd/system/dnsmasq-root.service <<'EOF'
|
||||||
|
[Unit]
|
||||||
|
Description=dnsmasq in root netns (intranet zone)
|
||||||
|
After=network-online.target
|
||||||
|
Wants=network-online.target
|
||||||
|
# Make sure the stock apt dnsmasq is out of the way:
|
||||||
|
# sudo systemctl disable --now dnsmasq
|
||||||
|
# sudo systemctl mask dnsmasq
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStartPre=/usr/sbin/dnsmasq --test -C /etc/dnsmasq-root/dnsmasq.conf
|
||||||
|
ExecStart=/usr/sbin/dnsmasq -k -C /etc/dnsmasq-root/dnsmasq.conf
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# validate and start
|
||||||
|
sudo systemctl daemon-reload
|
||||||
|
sudo systemctl enable --now dnsmasq-root
|
||||||
|
sudo systemctl status dnsmasq-root --no-pager
|
||||||
|
|
||||||
|
# verify it's bound only on br0 + tailscale0 (not on lo, not 0.0.0.0)
|
||||||
|
sudo ss -lnup | grep :53
|
||||||
|
|
||||||
|
# smoke test against the host's own br0 / tailscale0 IP
|
||||||
|
BR0_IP=$(ip -4 -o addr show br0 | awk '{print $4}' | cut -d/ -f1)
|
||||||
|
TS0_IP=$(ip -4 -o addr show tailscale0 | awk '{print $4}' | cut -d/ -f1)
|
||||||
|
dig @"$BR0_IP" psmf.intranet +short
|
||||||
|
dig @"$TS0_IP" psmf.intranet +short
|
||||||
|
dig @"$BR0_IP" cloudflare.com +short
|
||||||
|
```
|
||||||
28
servers/psmf/files/nginx/default
Normal file
28
servers/psmf/files/nginx/default
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
27
servers/psmf/files/nginx/psmf-new.intranet
Normal file
27
servers/psmf/files/nginx/psmf-new.intranet
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
28
servers/psmf/files/nginx/psmf.intranet
Normal file
28
servers/psmf/files/nginx/psmf.intranet
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
15
servers/psmf/files/srv/psmf/docker-compose.yml
Normal file
15
servers/psmf/files/srv/psmf/docker-compose.yml
Normal 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
|
||||||
21
servers/psmf/files/tailscaled-ts2.service
Normal file
21
servers/psmf/files/tailscaled-ts2.service
Normal 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
|
||||||
11
servers/psmf/files/ts2-netns-down
Normal file
11
servers/psmf/files/ts2-netns-down
Normal 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
|
||||||
55
servers/psmf/files/ts2-netns-up
Normal file
55
servers/psmf/files/ts2-netns-up
Normal 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
|
||||||
17
servers/psmf/files/ts2-netns.service
Normal file
17
servers/psmf/files/ts2-netns.service
Normal 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
|
||||||
2
servers/psmf/files/ts2-resolv.conf
Normal file
2
servers/psmf/files/ts2-resolv.conf
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# location: /etc/netns/ts2/resolv.conf
|
||||||
|
nameserver 1.1.1.1
|
||||||
6
servers/psmf/horst-2/crontab
Normal file
6
servers/psmf/horst-2/crontab
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# backups
|
||||||
|
15 11,15,19,22 * * * root /srv/bin/psmf-cli db backup --env-file ~/.psmf/horst-2.env --db psmf --dir /srv/backups/horst-2 -v >> /var/log/psmf-backup.log 2>&1
|
||||||
|
17 11,15,19,22 * * * root /srv/bin/psmf-cli db backup --env-file ~/.psmf/horst.env --db psmf --dir /srv/backups/horst -v >> /var/log/psmf-backup.log 2>&1
|
||||||
|
# prune backups
|
||||||
|
20 11,15,19,22 * * * root /srv/bin/psmf-cli db prune-backups --db psmf --dir /srv/backups/horst-2 --keep-within 2w --keep-weekly 8 --keep-monthly 120 >> /var/log/psmf-backup.log 2>&1
|
||||||
|
21 11,15,19,22 * * * root /srv/bin/psmf-cli db prune-backups --db psmf --dir /srv/backups/horst --keep-within 2w --keep-weekly 8 --keep-monthly 120 >> /var/log/psmf-backup.log 2>&1
|
||||||
93
servers/psmf/migration-plan.md
Normal file
93
servers/psmf/migration-plan.md
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
# Migration from horst-1 to horst-2
|
||||||
|
|
||||||
|
## postgres database
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# [DONE] install postgres
|
||||||
|
apt update
|
||||||
|
apt install -y curl ca-certificates gnupg lsb-release
|
||||||
|
|
||||||
|
# PGDG signing key (keyring-style, not the deprecated apt-key)
|
||||||
|
sudo install -d /usr/share/postgresql-common/pgdg
|
||||||
|
sudo curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc \
|
||||||
|
-o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc
|
||||||
|
|
||||||
|
# repo
|
||||||
|
echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] \
|
||||||
|
https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" \
|
||||||
|
| sudo tee /etc/apt/sources.list.d/pgdg.list
|
||||||
|
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y postgresql-18 postgresql-contrib-18
|
||||||
|
|
||||||
|
# backup database from horst-1
|
||||||
|
# users backup
|
||||||
|
pg_dumpall --globals-only -h 10.0.0.5 -U postgres > /tmp/pg-dumpall-globals
|
||||||
|
# data backup
|
||||||
|
pg_dump -h 10.0.0.5 -U postgres -C psmf > /tmp/psmf.pgsql
|
||||||
|
|
||||||
|
# restore backup of database from horst-1
|
||||||
|
# create users
|
||||||
|
cat /tmp/pg-dumpall-globals | psql
|
||||||
|
# restore psmf database
|
||||||
|
cat /tmp/psmf.pgsql | psql
|
||||||
|
|
||||||
|
# install docker oin horst-2
|
||||||
|
# Docker's GPG key (keyring, not apt-key)
|
||||||
|
sudo install -m 0755 -d /etc/apt/keyrings
|
||||||
|
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
|
||||||
|
-o /etc/apt/keyrings/docker.asc
|
||||||
|
sudo chmod a+r /etc/apt/keyrings/docker.asc
|
||||||
|
|
||||||
|
# repo
|
||||||
|
echo \
|
||||||
|
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
|
||||||
|
https://download.docker.com/linux/ubuntu \
|
||||||
|
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
|
||||||
|
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||||
|
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y \
|
||||||
|
docker-ce docker-ce-cli containerd.io \
|
||||||
|
docker-buildx-plugin docker-compose-plugin
|
||||||
|
|
||||||
|
|
||||||
|
# [DONE] dockerize php intranet app
|
||||||
|
# dockerized + upgraded to PHP 8.3.31
|
||||||
|
|
||||||
|
# [DONE] start psmf app on horst-2 and point it to database on horst
|
||||||
|
|
||||||
|
# [TODO] point php app on horst-1 to horst-2
|
||||||
|
|
||||||
|
# validate application is still working
|
||||||
|
# [OK] - wkhtml - PDF printing of html pages
|
||||||
|
# prepare local backups
|
||||||
|
# validate if pg sync to api still works from horst-1
|
||||||
|
# set sync to api on horst-2
|
||||||
|
# install nginx and configure default site as reverse proxy to horst-1
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y nginx
|
||||||
|
|
||||||
|
# drop the proxy config in place (file lives in this repo at servers/psmf/files/nginx/default)
|
||||||
|
sudo install -m 0644 -o root -g root \
|
||||||
|
servers/psmf/files/nginx/default /etc/nginx/sites-available/default
|
||||||
|
|
||||||
|
# sites-enabled/default is already a symlink to ../sites-available/default on a stock Ubuntu install
|
||||||
|
sudo nginx -t
|
||||||
|
sudo systemctl reload nginx
|
||||||
|
sudo systemctl enable nginx
|
||||||
|
|
||||||
|
# intranet vhosts: psmf.intranet -> horst-1, psmf-new.intranet -> local docker app
|
||||||
|
# (depends on the dnsmasq setup in servers/psmf/dns-configuration.md)
|
||||||
|
sudo install -m 0644 -o root -g root \
|
||||||
|
servers/psmf/files/nginx/psmf.intranet /etc/nginx/sites-available/psmf.intranet
|
||||||
|
sudo install -m 0644 -o root -g root \
|
||||||
|
servers/psmf/files/nginx/psmf-new.intranet /etc/nginx/sites-available/psmf-new.intranet
|
||||||
|
|
||||||
|
sudo ln -sf ../sites-available/psmf.intranet /etc/nginx/sites-enabled/psmf.intranet
|
||||||
|
sudo ln -sf ../sites-available/psmf-new.intranet /etc/nginx/sites-enabled/psmf-new.intranet
|
||||||
|
|
||||||
|
sudo nginx -t
|
||||||
|
sudo systemctl reload nginx
|
||||||
|
|
||||||
|
```
|
||||||
33
servers/psmf/readme.md
Normal file
33
servers/psmf/readme.md
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# Servers
|
||||||
|
|
||||||
|
### Horst
|
||||||
|
|
||||||
|
- ip: 10.0.0.5
|
||||||
|
- os: CentOS release 6.9 (Final)
|
||||||
|
- services:
|
||||||
|
- apache tcp/80
|
||||||
|
- postgres tcp/5432
|
||||||
|
- samba (not really in use)
|
||||||
|
- cronjobs
|
||||||
|
- /srv/bin/pg_psmf_dump.sh
|
||||||
|
- /srv/bin/psmf-prepare-tables.sh 2023 2027
|
||||||
|
- /srv/bin/psmf-api-sync.sh
|
||||||
|
|
||||||
|
- specials:
|
||||||
|
- some binaries/libraries relevant to PDF printing from the app WKHTML
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# crontab content
|
||||||
|
00 11,15,19,22 * * * root /srv/bin/pg_psmf_dump.sh
|
||||||
|
55 10,14,18,21 * * * root /srv/bin/psmf-prepare-tables.sh 2023 2027
|
||||||
|
05 11,15,19,22 * * * root /srv/bin/psmf-api-sync.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Problems
|
||||||
|
|
||||||
|
- operating system is already that old, that there is not reasonable and safe upgrade path to something current
|
||||||
|
|
||||||
|
|
||||||
|
### Horst-2
|
||||||
|
|
||||||
|
- ip: 10.0.0.6
|
||||||
39
servers/psmf/tailscale-second-instance.md
Normal file
39
servers/psmf/tailscale-second-instance.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
```bash
|
||||||
|
# Create namespace
|
||||||
|
sudo ip netns add ts2
|
||||||
|
|
||||||
|
# veth pair: host side <-> ns side
|
||||||
|
sudo ip link add veth-ts2 type veth peer name veth-ts2-ns
|
||||||
|
sudo ip link set veth-ts2-ns netns ts2
|
||||||
|
|
||||||
|
# Host side
|
||||||
|
sudo ip addr add 10.200.0.1/30 dev veth-ts2
|
||||||
|
sudo ip link set veth-ts2 up
|
||||||
|
|
||||||
|
# Namespace side
|
||||||
|
sudo ip -n ts2 addr add 10.200.0.2/30 dev veth-ts2-ns
|
||||||
|
sudo ip -n ts2 link set veth-ts2-ns up
|
||||||
|
sudo ip -n ts2 link set lo up
|
||||||
|
sudo ip -n ts2 route add default via 10.200.0.1
|
||||||
|
|
||||||
|
# DNS inside the netns
|
||||||
|
sudo mkdir -p /etc/netns/ts2
|
||||||
|
echo "nameserver 1.1.1.1" | sudo tee /etc/netns/ts2/resolv.conf
|
||||||
|
|
||||||
|
# NAT from the netns out to the world (replace eth0 with your egress iface)
|
||||||
|
sudo sysctl -w net.ipv4.ip_forward=1
|
||||||
|
sudo iptables -t nat -A POSTROUTING -s 10.200.0.0/30 -o br0 -j MASQUERADE
|
||||||
|
sudo iptables -A FORWARD -i veth-ts2 -o br0 -j ACCEPT
|
||||||
|
sudo iptables -A FORWARD -o veth-ts2 -i br0 -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||||
|
|
||||||
|
|
||||||
|
# quick sanity check
|
||||||
|
sudo ip netns exec ts2 curl https://controlplane.tailscale.com
|
||||||
|
# expect: "OK"
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# ts2 alias
|
||||||
|
echo 'alias ts2="sudo ip netns exec ts2 tailscale --socket=/run/tailscale-ts2/tailscaled.sock"' \
|
||||||
|
| sudo tee /etc/profile.d/tailscale-ts2.sh
|
||||||
|
```
|
||||||
20
vms/docker-dev-22/psmf-data-sync/.env
Normal file
20
vms/docker-dev-22/psmf-data-sync/.env
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# Image (built by .gitea/workflows/build.yaml)
|
||||||
|
# IMAGE_REPO is the Gitea repo path, e.g. "jan/psmf-data-sync"
|
||||||
|
IMAGE_REPO=gitea.home.hrajfrisbee.cz/psmf/psmf-data-syncer
|
||||||
|
IMAGE_TAG=0.2
|
||||||
|
|
||||||
|
# Host port to publish the syncer on (container listens on 8002 internally)
|
||||||
|
HOST_PORT=8003
|
||||||
|
|
||||||
|
# External Postgres the syncer restores into
|
||||||
|
DB_HOST=192.168.123.23
|
||||||
|
DB_PORT=5432
|
||||||
|
DB_NAME=psmf-dev
|
||||||
|
DB_USER=psmf-dev
|
||||||
|
DB_PASSWORD=** masked even when it is so secret **
|
||||||
|
|
||||||
|
# Which Redis DB index to use (0-15)
|
||||||
|
REDIS_DB=0
|
||||||
|
|
||||||
|
# info | debug
|
||||||
|
LOG_LEVEL=debug
|
||||||
28
vms/docker-dev-22/psmf-data-sync/docker-compose.yml
Normal file
28
vms/docker-dev-22/psmf-data-sync/docker-compose.yml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
services:
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
command: ["redis-server", "--appendonly", "yes"]
|
||||||
|
volumes:
|
||||||
|
- redis-data:/data
|
||||||
|
|
||||||
|
psmf-data-sync:
|
||||||
|
image: ${IMAGE_REPO}:${IMAGE_TAG:-latest}
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
- redis
|
||||||
|
ports:
|
||||||
|
- "${HOST_PORT:-8003}:8002"
|
||||||
|
environment:
|
||||||
|
DB_HOST: ${DB_HOST}
|
||||||
|
DB_PORT: ${DB_PORT:-5432}
|
||||||
|
DB_NAME: ${DB_NAME}
|
||||||
|
DB_USER: ${DB_USER}
|
||||||
|
DB_PASSWORD: ${DB_PASSWORD}
|
||||||
|
REDIS_HOST: redis
|
||||||
|
REDIS_PORT: 6379
|
||||||
|
REDIS_DB: ${REDIS_DB:-0}
|
||||||
|
LOG_LEVEL: ${LOG_LEVEL:-info}
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
redis-data:
|
||||||
22
vms/docker-dev-22/readme.md
Normal file
22
vms/docker-dev-22/readme.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
## docker
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# prereqs + keyring
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y ca-certificates curl
|
||||||
|
sudo install -m 0755 -d /etc/apt/keyrings
|
||||||
|
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
|
||||||
|
sudo chmod a+r /etc/apt/keyrings/docker.asc
|
||||||
|
|
||||||
|
# repo
|
||||||
|
echo \
|
||||||
|
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
|
||||||
|
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
|
||||||
|
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||||
|
|
||||||
|
# install
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
22
vms/storage-23/pg_hba.conf
Normal file
22
vms/storage-23/pg_hba.conf
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Database administrative login by Unix domain socket
|
||||||
|
local all postgres peer
|
||||||
|
|
||||||
|
# TYPE DATABASE USER ADDRESS METHOD
|
||||||
|
|
||||||
|
# "local" is for Unix domain socket connections only
|
||||||
|
local all all peer
|
||||||
|
# IPv4 local connections:
|
||||||
|
host all all 127.0.0.1/32 scram-sha-256
|
||||||
|
# IPv6 local connections:
|
||||||
|
host all all ::1/128 scram-sha-256
|
||||||
|
# Allow replication connections from localhost, by a user with the
|
||||||
|
# replication privilege.
|
||||||
|
local replication all peer
|
||||||
|
host replication all 127.0.0.1/32 scram-sha-256
|
||||||
|
host replication all ::1/128 scram-sha-256
|
||||||
|
|
||||||
|
# TYPE DATABASE USER ADDRESS METHOD
|
||||||
|
host psmf psmf 192.168.123.21/32 md5
|
||||||
|
host psmfapi psmf 192.168.123.21/32 md5
|
||||||
|
host postgres psmf 192.168.123.21/32 md5
|
||||||
|
host psmf-dev psmf-dev 192.168.123.22/32 md5
|
||||||
Reference in New Issue
Block a user