331 lines
7.9 KiB
Python
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 |