切换公网域名为cdis.cn并配置生产HTTPS反代
This commit is contained in:
parent
474b424023
commit
cba6442bde
@ -10,9 +10,9 @@ try:
|
|||||||
commands = [
|
commands = [
|
||||||
"systemctl is-active fdm-studio; ss -ltnp '( sport = :9999 )'",
|
"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",
|
"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",
|
'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/odacm.cn/fullchain.pem -noout -issuer -subject -dates",
|
'openssl x509 -in /etc/letsencrypt/live/cdis.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",
|
'tail -n 8 /var/log/nginx/fdm-cdis-access.log; tail -n 8 /var/log/nginx/fdm-cdis-error.log',
|
||||||
]
|
]
|
||||||
for command in commands:
|
for command in commands:
|
||||||
print(command, flush=True)
|
print(command, flush=True)
|
||||||
|
|||||||
11
deploy/nginx-cdis-http.conf
Normal file
11
deploy/nginx-cdis-http.conf
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
25
deploy/nginx-cdis-https.conf
Normal file
25
deploy/nginx-cdis-https.conf
Normal 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
79
deploy/switch-domain.py
Normal 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()
|
||||||
@ -29,7 +29,7 @@ try:
|
|||||||
stamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
|
stamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
|
||||||
release = f"/opt/fdm/releases/{stamp}"
|
release = f"/opt/fdm/releases/{stamp}"
|
||||||
backup = f"/var/backups/fdm/{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()
|
sftp = client.open_sftp()
|
||||||
binary = root / "artifacts/fdm-studio"
|
binary = root / "artifacts/fdm-studio"
|
||||||
sftp.put(str(binary), release + "/fdm-studio")
|
sftp.put(str(binary), release + "/fdm-studio")
|
||||||
@ -37,16 +37,16 @@ try:
|
|||||||
expected = hashlib.sha256(binary.read_bytes()).hexdigest()
|
expected = hashlib.sha256(binary.read_bytes()).hexdigest()
|
||||||
run(f"echo '{expected} {release}/fdm-studio' | sha256sum -c -")
|
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/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("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(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("sleep 2 && curl -fsS http://127.0.0.1:19999/healthz")
|
||||||
run(f"systemctl stop fdm-candidate-{stamp.lower()}")
|
run(f"systemctl stop fdm-candidate-{stamp.lower()}")
|
||||||
switched = True
|
switched = True
|
||||||
run(f"ln -sfn {release} /opt/fdm/current")
|
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("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")
|
run("systemctl is-enabled certbot.timer || true")
|
||||||
sftp.close()
|
sftp.close()
|
||||||
print("部署完成:" + release, flush=True)
|
print("部署完成:" + release, flush=True)
|
||||||
@ -56,7 +56,7 @@ except Exception:
|
|||||||
run("systemctl stop fdm-studio || true")
|
run("systemctl stop fdm-studio || true")
|
||||||
if previous:
|
if previous:
|
||||||
run(f"ln -sfn {previous} /opt/fdm/current && systemctl start fdm-studio")
|
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
|
raise
|
||||||
finally:
|
finally:
|
||||||
client.close()
|
client.close()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user