~gitpocket/gitpocket

8
afe9eeb7545ead1afb02033900068b2c60de3277
mainfeed-discovery
gitpocket/deploy/domains.sh -rwxr-xr-x3.2 KiB ViewLogBlameView rawPermalink 1a064e3197 build(deploy): front the origin with cloudflare and drop certbot 11 hours ago
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
#!/bin/sh
set -eu
bin=${GITPOCKET_BIN:-/usr/local/bin/gitpocket}
root=${GITPOCKET_ROOT:-/srv/gitpocket}
user=${GITPOCKET_USER:-git}
port=${GITPOCKET_PORT:-3200}
conf=${GITPOCKET_NGINX:-/etc/nginx/conf.d/gitpocket-domains.conf}
cert=${GITPOCKET_CERT:-/etc/gitpocket/origin.pem}
key=${GITPOCKET_KEY:-/etc/gitpocket/origin.key}
cloudflare=${GITPOCKET_CLOUDFLARE:-/etc/gitpocket/cloudflare}

domains=$(runuser -u "$user" -- "$bin" -root "$root" domains | grep -E '^[a-z0-9.-]+$' || true)

render() {
    [ -n "$domains" ] || return 0
    names=$(printf ' %s' $domains)
    cat <<CONF
server {
    listen 80;
    listen [::]:80;
    server_name$names;
    include snippets/gitpocket-cloudflare.conf;
    location / { return 301 https://\$host\$request_uri; }
}
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name$names;
    ssl_certificate $cert;
    ssl_certificate_key $key;
    ssl_protocols TLSv1.2 TLSv1.3;
    include snippets/gitpocket-cloudflare.conf;
    client_max_body_size 1m;
    add_header Strict-Transport-Security "max-age=31536000" always;
    gzip on;
    gzip_proxied any;
    gzip_vary on;
    gzip_types text/css text/plain text/javascript application/javascript image/svg+xml application/json application/xml;
    location / {
        limit_except GET HEAD { deny all; }
        proxy_pass http://127.0.0.1:$port;
        proxy_http_version 1.1;
        proxy_set_header Host \$host;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-For \$remote_addr;
        proxy_set_header Cookie "";
    }
}
CONF
}

apply() {
    next=$(mktemp)
    render > "$next"
    if [ -f "$conf" ] && cmp -s "$next" "$conf"; then
        rm -f "$next"
        return 0
    fi
    [ -f "$conf" ] && cp "$conf" "$conf.old"
    mv "$next" "$conf"
    chmod 644 "$conf"
    if nginx -t 2>/dev/null; then
        systemctl reload nginx
    else
        echo "nginx rejected $conf, restoring" >&2
        if [ -f "$conf.old" ]; then mv "$conf.old" "$conf"; else rm -f "$conf"; fi
        exit 1
    fi
}

hostnames() {
    [ -r "$cloudflare" ] || return 0
    python3 - "$cloudflare" $domains <<'PY'
import json, sys, urllib.request
env = dict(l.strip().split("=", 1) for l in open(sys.argv[1]) if "=" in l)
want = set(sys.argv[2:]) - set(env.get("CF_SKIP", "").split())
base = f"https://api.cloudflare.com/client/v4/zones/{env['CF_ZONE']}/custom_hostnames"
def call(method, url, body=None):
    req = urllib.request.Request(url, method=method, data=json.dumps(body).encode() if body else None,
        headers={"Authorization": "Bearer " + env["CF_TOKEN"], "Content-Type": "application/json"})
    with urllib.request.urlopen(req, timeout=30) as r:
        return json.load(r)
have, page = {}, 1
while True:
    res = call("GET", f"{base}?per_page=50&page={page}")["result"]
    have.update({h["hostname"]: h["id"] for h in res})
    if len(res) < 50:
        break
    page += 1
for name in sorted(want - have.keys()):
    try:
        call("POST", base, {"hostname": name, "ssl": {"method": "http", "type": "dv"}})
    except Exception as e:
        print(f"custom hostname {name}: {e}", file=sys.stderr)
for name in sorted(have.keys() - want):
    call("DELETE", f"{base}/{have[name]}")
PY
}

apply
hostnames