切换公网域名为cdis.cn并配置生产HTTPS反代

This commit is contained in:
xuans 2026-09-19 09:58:33 +08:00
parent 474b424023
commit cba6442bde
5 changed files with 123 additions and 8 deletions

View File

@ -10,9 +10,9 @@ try:
commands = [
"systemctl is-active fdm-studio; ss -ltnp '( sport = :9999 )'",
"grep -R -n -E 'listen|server_name' /etc/nginx/conf.d /etc/nginx/sites-enabled 2>/dev/null",
"curl -sS -I --resolve odacm.cn:443:127.0.0.1 https://odacm.cn; curl -sS -I http://odacm.cn",
"openssl x509 -in /etc/letsencrypt/live/odacm.cn/fullchain.pem -noout -issuer -subject -dates",
"tail -n 8 /var/log/nginx/fdm-access.log; tail -n 8 /var/log/nginx/fdm-error.log",
'curl -sS -I --resolve cdis.cn:443:127.0.0.1 https://cdis.cn; curl -sS -I http://cdis.cn',
'openssl x509 -in /etc/letsencrypt/live/cdis.cn/fullchain.pem -noout -issuer -subject -dates',
'tail -n 8 /var/log/nginx/fdm-cdis-access.log; tail -n 8 /var/log/nginx/fdm-cdis-error.log',
]
for command in commands:
print(command, flush=True)

View File

@ -0,0 +1,11 @@
server {
listen 80;
listen [::]:80;
server_name cdis.cn;
location ^~ /.well-known/acme-challenge/ {
root /var/lib/letsencrypt;
}
location / {
return 308 https://cdis.cn$request_uri;
}
}

View File

@ -0,0 +1,25 @@
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name cdis.cn;
ssl_certificate /etc/letsencrypt/live/cdis.cn/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/cdis.cn/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
access_log /var/log/nginx/fdm-cdis-access.log;
error_log /var/log/nginx/fdm-cdis-error.log warn;
add_header X-Content-Type-Options nosniff always;
add_header Referrer-Policy strict-origin-when-cross-origin always;
location / {
proxy_pass http://127.0.0.1:9999;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Connection '';
proxy_connect_timeout 5s;
proxy_read_timeout 60s;
}
}

79
deploy/switch-domain.py Normal file
View File

@ -0,0 +1,79 @@
import getpass
import json
import time
from datetime import datetime, timezone
from pathlib import Path
import paramiko
from deploy import dns_request
DOMAIN = 'cdis.cn'
HOST = '47.108.78.12'
ROOT = Path(__file__).resolve().parent
def main():
password = getpass.getpass('SSH password: ')
key = getpass.getpass('Aliyun AccessKey ID: ')
secret = getpass.getpass('Aliyun AccessKey secret: ')
client = paramiko.SSHClient()
client.load_host_keys(str(Path.home() / '.ssh' / 'known_hosts'))
client.connect(HOST, username='root', password=password, timeout=20)
def run(command, timeout=60):
print(command, flush=True)
_, out, err = client.exec_command(command, timeout=timeout)
text = out.read().decode() + err.read().decode()
print(text, flush=True)
if out.channel.recv_exit_status():
raise RuntimeError('Remote command failed')
return text.strip()
try:
result = dns_request('DescribeDomainRecords', key, secret,
DomainName=DOMAIN, PageSize='500')
records = [r for r in result.get('DomainRecords', {}).get('Record', [])
if r['RR'] == '@' and r['Type'] in ('A', 'AAAA', 'CNAME')]
print(json.dumps(records, ensure_ascii=True), flush=True)
if any(r['Type'] != 'A' or r['Status'] != 'ENABLE' for r in records):
raise RuntimeError('Unexpected root DNS records; no changes made')
stamp = datetime.now(timezone.utc).strftime('%Y%m%dT%H%M%SZ')
backup = '/var/backups/fdm/domain-' + stamp
run('nginx -t && systemctl is-active fdm-studio')
run(f'install -d -m 755 {backup} /var/lib/letsencrypt/.well-known/acme-challenge')
run(f'cp -a /etc/nginx/conf.d {backup}/')
with client.open_sftp() as sftp:
with sftp.open(backup + '/dns-before.json', 'w') as output:
output.write(json.dumps(records))
sftp.put(str(ROOT / 'nginx-cdis-http.conf'), '/etc/nginx/conf.d/fdm-cdis.conf')
run('nginx -t && systemctl reload nginx')
for record in records:
if record['Value'] != HOST:
dns_request('UpdateDomainRecord', key, secret, RecordId=record['RecordId'],
RR='@', Type='A', Value=HOST, TTL='600')
if not records:
dns_request('AddDomainRecord', key, secret, DomainName=DOMAIN,
RR='@', Type='A', Value=HOST, TTL='600')
key = secret = None
for attempt in range(30):
answer = run(f'dig +short @223.5.5.5 {DOMAIN} A')
if answer.splitlines() == [HOST]:
break
time.sleep(20)
else:
raise RuntimeError('DNS propagation pending; rerun after propagation')
run(f'certbot certonly --webroot -w /var/lib/letsencrypt -d {DOMAIN} --cert-name {DOMAIN} --non-interactive --agree-tos --register-unsafely-without-email --server https://acme-v02.api.letsencrypt.org/directory', timeout=420)
with client.open_sftp() as sftp:
sftp.put(str(ROOT / 'nginx-cdis-https.conf'), '/etc/nginx/conf.d/fdm-cdis-ssl.conf')
run('nginx -t && systemctl reload nginx')
run(f'curl -fsS --resolve {DOMAIN}:443:127.0.0.1 https://{DOMAIN}/healthz')
run(f'openssl x509 -in /etc/letsencrypt/live/{DOMAIN}/fullchain.pem -noout -issuer -subject -dates')
run('systemctl is-enabled certbot.timer || true')
print('Domain switch complete', flush=True)
finally:
client.close()
if __name__ == '__main__':
main()

View File

@ -29,7 +29,7 @@ try:
stamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
release = f"/opt/fdm/releases/{stamp}"
backup = f"/var/backups/fdm/{stamp}"
run(f"install -d -m 755 {release} {backup} && cp -a /etc/nginx/conf.d/fdm-odacm.conf {backup}/")
run(f'install -d -m 755 {release} {backup} && cp -a /etc/nginx/conf.d/fdm-cdis.conf {backup}/')
sftp = client.open_sftp()
binary = root / "artifacts/fdm-studio"
sftp.put(str(binary), release + "/fdm-studio")
@ -37,16 +37,16 @@ try:
expected = hashlib.sha256(binary.read_bytes()).hexdigest()
run(f"echo '{expected} {release}/fdm-studio' | sha256sum -c -")
sftp.put(str(root / "deploy/fdm-studio.service"), "/etc/systemd/system/fdm-studio.service")
sftp.put(str(root / "deploy/nginx-program-http.conf"), release + "/nginx-http.conf")
sftp.put(str(root / 'deploy/nginx-cdis-http.conf'), release + '/nginx-http.conf')
run("systemctl daemon-reload")
run(f"systemd-run --unit=fdm-candidate-{stamp.lower()} --property=DynamicUser=yes {release}/fdm-studio -listen 127.0.0.1:19999")
run("sleep 2 && curl -fsS http://127.0.0.1:19999/healthz")
run(f"systemctl stop fdm-candidate-{stamp.lower()}")
switched = True
run(f"ln -sfn {release} /opt/fdm/current")
run(f"cp {release}/nginx-http.conf /etc/nginx/conf.d/fdm-odacm.conf && nginx -t && systemctl reload nginx")
run(f'cp {release}/nginx-http.conf /etc/nginx/conf.d/fdm-cdis.conf && nginx -t && systemctl reload nginx')
run("sleep 3 && systemctl enable fdm-studio && systemctl restart fdm-studio && sleep 3 && systemctl is-active fdm-studio")
run("curl -fsS http://127.0.0.1:9999/healthz && curl -fsS --resolve odacm.cn:443:127.0.0.1 https://odacm.cn/healthz")
run('curl -fsS http://127.0.0.1:9999/healthz && curl -fsS --resolve cdis.cn:443:127.0.0.1 https://cdis.cn/healthz')
run("systemctl is-enabled certbot.timer || true")
sftp.close()
print("部署完成:" + release, flush=True)
@ -56,7 +56,7 @@ except Exception:
run("systemctl stop fdm-studio || true")
if previous:
run(f"ln -sfn {previous} /opt/fdm/current && systemctl start fdm-studio")
run(f"cp {backup}/fdm-odacm.conf /etc/nginx/conf.d/fdm-odacm.conf && nginx -t && systemctl reload nginx")
run(f'cp {backup}/fdm-cdis.conf /etc/nginx/conf.d/fdm-cdis.conf && nginx -t && systemctl reload nginx')
raise
finally:
client.close()