site-manager/sites.py

331 lines
7.9 KiB
Python

import os
import json
import re
def load_sites():
if not os.path.isfile('sites.json'):
with open('sites.json', 'w') as file:
file.write('[]')
with open('sites.json', 'r') as file:
sites = json.loads(file.read())
return sites
def get_info():
sites = load_sites()
if not sites:
return {
'total_sites': 0,
'active_sites': 0
}
total_sites = len(sites)
active_sites = 0
for site in sites:
if site['active']:
active_sites += 1
return {
'total_sites': total_sites,
'active_sites': active_sites
}
def get_site(name):
sites = load_sites()
for site in sites:
if site['name'] == name:
return site
return False
def add_site(name, domain):
sites = load_sites()
domain = domain.lower().strip()
# Check domain
if re.search(r'[^a-zA-Z0-9.-]', domain):
return False
# Make sure certs directory exists
if not os.path.isdir('certs'):
os.mkdir('certs')
if is_icann(domain):
tlsa = "Not needed"
else:
# Generate TLSA record
tlsa = os.popen(f'./tlsa.sh {domain}').read().strip()
print(tlsa)
if not tlsa:
return False
id = len(sites)
for site in sites:
if site['id'] >= id:
id = site['id'] + 1
sites.append({
'name': name,
'domain': domain,
'active': False,
'tlsa': tlsa,
'id': id
})
with open('sites.json', 'w') as file:
file.write(json.dumps(sites))
return True
def add_alt_domain(name, domain):
sites = load_sites()
for site in sites:
if site['name'] == name:
if 'alt_domains' not in site:
site['alt_domains'] = []
site['alt_domains'].append(domain)
if is_icann(domain):
tlsa = "Not needed"
else:
# Generate TLSA record
tlsa = os.popen(f'./tlsa.sh {domain}').read().strip()
print(tlsa)
if not tlsa:
return False
if 'alt_tlsa' not in site:
site['alt_tlsa'] = {}
site['alt_tlsa'][domain] = tlsa
with open('sites.json', 'w') as file:
file.write(json.dumps(sites))
return True
return False
def enable(name, enable):
sites = load_sites()
if enable == 'on':
enable = True
# Create site file
write_nginx_conf(name)
else:
enable = False
# Delete site file
os.remove(f'/etc/nginx/sites-enabled/{name}')
for site in sites:
if site['name'] == name:
site['active'] = enable
with open('sites.json', 'w') as file:
file.write(json.dumps(sites))
return True
return False
def get_content(site):
site = get_site(site)
id = site['id']
path = f'/var/www/{id}'
if not os.path.isdir(path):
return []
files = os.listdir(path)
return files
def get_dns_info(site):
# Get public ip of server
public_ip = os.popen('curl ipinfo.io/ip').read().strip()
# Get domains
domains = get_site(site)
if not domains:
return False
main = domains['domain']
tlsa = domains['tlsa']
alt = []
if 'alt_domains' in domains:
alt = domains['alt_domains']
info = [{
'domain': main,
'ip': public_ip,
'tlsa': tlsa
}]
for alt_domain in alt:
alt_tlsa = domains['alt_tlsa'][alt_domain]
info.append({
'domain': alt_domain,
'ip': public_ip,
'tlsa': alt_tlsa
})
return info
def write_nginx_conf(site):
site = get_site(site)
domain = site['domain']
id = site['id']
location = f'/var/www/{id}'
ssl = ""
if not is_icann(domain):
ssl = f'''
listen 443 ssl;
ssl_certificate /root/site-manager/certs/{domain}/cert.crt;
ssl_certificate_key /root/site-manager/certs/{domain}/cert.key;
'''
conf = f'''
server {{
listen 80;
listen [::]:80;
root '{location}';
index index.html;
server_name {domain} *.{domain};
location / {{
try_files $uri $uri/ @htmlext;
}}
location ~ \.html$ {{
try_files $uri =404;
}}
location @htmlext {{
rewrite ^(.*)$ $1.html last;
}}
error_page 404 /404.html;
location = /404.html {{
internal;
}}
location = /.well-known/wallets/HNS {{
add_header Cache-Control 'must-revalidate';
add_header Content-Type text/plain;
}}
{ssl}
}}
'''
# Add alt domains
if 'alt_domains' in site:
for alt in site['alt_domains']:
if not is_icann(alt):
ssl = f'''
listen 443 ssl;
ssl_certificate /root/site-manager/certs/{alt}/cert.crt;
ssl_certificate_key /root/site-manager/certs/{alt}/cert.key;
'''
else:
ssl = ""
conf += f'''
server {{
listen 80;
listen [::]:80;
root '{location}';
index index.html;
server_name {alt} *.{alt};
location / {{
try_files $uri $uri/ @htmlext;
}}
location ~ \.html$ {{
try_files $uri =404;
}}
location @htmlext {{
rewrite ^(.*)$ $1.html last;
}}
error_page 404 /404.html;
location = /404.html {{
internal;
}}
location = /.well-known/wallets/HNS {{
add_header Cache-Control 'must-revalidate';
add_header Content-Type text/plain;
}}
{ssl}
}}
'''
with open(f'/etc/nginx/sites-enabled/{id}.conf', 'w') as file:
file.write(conf)
# Restart nginx
os.system('systemctl restart nginx')
# Create certs for ICANN domains
icann_domains = []
if is_icann(domain):
icann_domains.append(domain)
if 'alt_domains' in site:
for alt in site['alt_domains']:
if is_icann(alt):
icann_domains.append(alt)
if len(icann_domains) > 0:
email = f'admin@{icann_domains[0]}'
icann_domains = " -d ".join(icann_domains)
icann_domains = f'-d {icann_domains}'
os.system(f'certbot --nginx {icann_domains} --non-interactive --agree-tos --email {email} --redirect')
return True
def is_icann(domain):
# Check if domain list is downloaded yet
if not os.path.isfile('icann.txt'):
os.system('wget https://data.iana.org/TLD/tlds-alpha-by-domain.txt -O icann.txt')
tlds = open('icann.txt', 'r').read().split('\n')
# Remove any comments
tlds = [tld for tld in tlds if not tld.startswith('#')]
if domain.split('.')[-1].upper() in tlds:
return True
return False
def clone_git(name, url):
site = get_site(name)
id = site['id']
path = f'/var/www/{id}'
if not os.path.isdir(path):
os.mkdir(path)
os.system(f'git clone {url} {path}')
with open('sites.json', 'r') as file:
sites = json.loads(file.read())
for site in sites:
if site['name'] == name:
site['git'] = url
with open('sites.json', 'w') as file:
file.write(json.dumps(sites))
return True
return True
def pull_git(name):
site = get_site(name)
id = site['id']
path = f'/var/www/{id}'
if not os.path.isdir(path):
return False
# Check if it's a git repo
if not os.path.isdir(f'{path}/.git'):
# Remove git from sites.json
with open('sites.json', 'r') as file:
sites = json.loads(file.read())
for site in sites:
if site['name'] == name:
del site['git']
with open('sites.json', 'w') as file:
file.write(json.dumps(sites))
return False
os.system(f'cd {path} && git pull')
return True