24 Commits

Author SHA1 Message Date
6741f8cac2 main: Add route to get site count
All checks were successful
Build Docker / Build Master (push) Successful in 24s
Build Docker / Build Bot (push) Successful in 22s
2023-09-18 14:42:43 +10:00
0365832e40 actions: Build release for arm 2023-09-18 14:38:37 +10:00
40515700d1 actions: Build for arm
All checks were successful
Build Docker / Build Master (push) Successful in 22s
Build Docker / Build Bot (push) Successful in 21s
2023-09-17 08:48:51 +10:00
c130bfed69 fix: Set domain to lower in api requests
Some checks failed
Build Docker / Build Master (push) Failing after 12s
Build Docker / Build Bot (push) Successful in 46s
2023-09-17 08:47:36 +10:00
d19a121005 master: Fixed private ip reference
Some checks failed
Build Docker / Build Master (push) Successful in 40s
Build Docker / Build Bot (push) Failing after 17m41s
2023-09-16 17:10:20 +10:00
d0ff839ff4 main: Added register error messages
All checks were successful
Build Docker / Build Bot (push) Successful in 22s
Build Docker / Build Master (push) Successful in 29s
2023-09-03 13:48:26 +10:00
9469f23f50 main: Updated email for licence
All checks were successful
Build Docker / Build Bot (push) Successful in 23s
Build Docker / Build Master (push) Successful in 30s
2023-09-02 14:14:00 +10:00
639dc9065c main: Fixed typo
All checks were successful
Build Docker / Build Master (push) Successful in 27s
Build Docker / Build Bot (push) Successful in 28s
2023-09-02 14:03:12 +10:00
5b5dbd6660 main: Updated buy licence link
All checks were successful
Build Docker / Build Bot (push) Successful in 23s
Build Docker / Build Master (push) Successful in 30s
2023-09-02 14:00:27 +10:00
95aa476c64 main: Updated nav bar
All checks were successful
Build Docker / Build Bot (push) Successful in 30s
Build Docker / Build Master (push) Successful in 32s
2023-09-02 13:50:22 +10:00
79a8e092eb main: Updated register page
All checks were successful
Build Docker / Build Bot (push) Successful in 23s
Build Docker / Build Master (push) Successful in 30s
2023-09-02 13:48:10 +10:00
8ab4ed574f main: Updated assets location
All checks were successful
Build Docker / Build Master (push) Successful in 28s
Build Docker / Build Bot (push) Successful in 28s
2023-09-02 13:31:47 +10:00
58bce1e8bf main: Added initial bootstrap site
All checks were successful
Build Docker / Build Master (push) Successful in 42s
Build Docker / Build Bot (push) Successful in 48s
2023-09-02 13:29:12 +10:00
75b4f979e3 main: Added favicon to template
All checks were successful
Build Docker / Build Bot (push) Successful in 24s
Build Docker / Build Master (push) Successful in 25s
2023-08-26 09:39:05 +10:00
c837d5d528 main: Cleaned up list items
All checks were successful
Build Docker / Build Bot (push) Successful in 23s
Build Docker / Build Master (push) Successful in 23s
2023-08-26 09:33:57 +10:00
a8e2d90dc6 main: Added safe tag to allow list items
All checks were successful
Build Docker / Build Bot (push) Successful in 25s
Build Docker / Build Master (push) Successful in 28s
2023-08-26 09:30:09 +10:00
494a7e28a6 main: Test using templates
All checks were successful
Build Docker / Build Bot (push) Successful in 23s
Build Docker / Build Master (push) Successful in 28s
2023-08-25 23:26:44 +10:00
076303d475 worker: Revert using tmfs 2023-08-25 23:22:42 +10:00
ac054156ef main: Cleaned up public page
All checks were successful
Build Docker / Build Bot (push) Successful in 25s
Build Docker / Build Master (push) Successful in 28s
2023-08-25 22:57:11 +10:00
2bc34c1aca main: Fixed html a tag
All checks were successful
Build Docker / Build Bot (push) Successful in 25s
Build Docker / Build Master (push) Successful in 26s
2023-08-25 22:53:35 +10:00
490176ab04 main: Fixed quote escaping
All checks were successful
Build Docker / Build Bot (push) Successful in 20s
Build Docker / Build Master (push) Successful in 26s
2023-08-25 22:50:51 +10:00
01b4ee9fd5 main: Updated home page to have site links
All checks were successful
Build Docker / Build Bot (push) Successful in 25s
Build Docker / Build Master (push) Successful in 28s
2023-08-25 22:47:19 +10:00
1bafb844f2 worker: Set the default storage size to 5gb
All checks were successful
Build Docker / Build Bot (push) Successful in 25s
Build Docker / Build Master (push) Successful in 27s
2023-08-25 22:35:18 +10:00
f23f361ceb worker: Set docker to use HNSProxy to allow for HNS resolution 2023-08-25 22:34:50 +10:00
26 changed files with 552 additions and 57 deletions

View File

@@ -10,7 +10,7 @@ on:
jobs:
Build Master:
runs-on: ubuntu-latest
runs-on: [ubuntu-latest, arm]
steps:
- name: Checkout
uses: actions/checkout@v2
@@ -51,7 +51,7 @@ jobs:
Build Bot:
runs-on: ubuntu-latest
runs-on: [ubuntu-latest, arm]
steps:
- name: Checkout
uses: actions/checkout@v2

View File

@@ -8,7 +8,7 @@ on:
jobs:
Build Master:
runs-on: ubuntu-latest
runs-on: [ubuntu-latest,arm]
steps:
- name: Checkout
uses: actions/checkout@v2
@@ -34,7 +34,7 @@ jobs:
docker push git.woodburn.au/nathanwoodburn/hnshosting-master:release
Build Bot:
runs-on: ubuntu-latest
runs-on: [ubuntu-latest,arm]
steps:
- name: Checkout
uses: actions/checkout@v2

View File

@@ -0,0 +1,10 @@
html {
background-color: black;
color: white;
font-family: 'Roboto', sans-serif;
font-size: 16px;
text-align: center;
}
li {
list-style-type: none;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@@ -1,4 +1,4 @@
from flask import Flask, make_response, redirect, request, jsonify
from flask import Flask, make_response, redirect, request, jsonify, render_template, send_from_directory
import dotenv
import os
import requests
@@ -206,6 +206,7 @@ def list_workers():
@app.route('/site-info', methods=['GET'])
def site_status():
domain = request.args.get('domain')
domain = domain.lower()
if domain == None:
return jsonify({'error': 'Invalid domain', 'success': 'false'})
@@ -236,6 +237,7 @@ def site_status():
@app.route('/info')
def site_status_human():
domain = request.args.get('domain')
domain = domain.lower()
if domain == None:
return "<h1>Invalid domain</h1>"
@@ -265,6 +267,7 @@ def site_status_human():
@app.route('/tlsa', methods=['GET'])
def tlsa():
domain = request.args.get('domain')
domain = domain.lower()
if domain == None:
return jsonify({'error': 'Invalid domain', 'success': 'false'})
@@ -329,7 +332,7 @@ def stripeapi():
message = "From: " + from_email + "\nTo: " + email + \
"\nSubject: Your Licence key\n\nHello,\n\n"\
+"This email contains your licence key for your new wordpress site.\n" \
+"You can redeem this key via the discord bot or api.\n\n"\
+"You can redeem this key via the discord bot or at https://hnshosting.au/register\n\n"\
+"Your licence key is: " + licence_key +"\nThanks,\nHNSHosting"
server.sendmail(from_email, email, message)
@@ -401,7 +404,7 @@ def workerIP_PRIV(worker):
ip = None
for line in workers_file.readlines():
if worker == line.split(':')[0]:
ip = line.split(':')[2].strip('\n')
ip = line.split(':')[1].strip('\n')
break
workers_file.close()
@@ -419,7 +422,7 @@ def workerIP(worker):
ip = None
for line in workers_file.readlines():
if worker == line.split(':')[0]:
ip = line.split(':')[1].strip('\n')
ip = line.split(':')[2].strip('\n')
break
workers_file.close()
@@ -429,17 +432,7 @@ def workerIP(worker):
# Home page
@app.route('/')
def home():
# Show stats and info
# Get worker info
workers = []
try:
workers_file = open('/data/workers.txt', 'r')
workers = workers_file.readlines()
workers_file.close()
except FileNotFoundError:
pass
# Show index template
# Get site info
sites = []
try:
@@ -449,44 +442,131 @@ def home():
except FileNotFoundError:
pass
# Get licence info
licences = []
return render_template('index.html', site_count = str(len(sites)))
# Register page
@app.route('/register', methods=['GET'])
def register():
buy_licence_link = os.getenv('BUY_LICENCE_LINK')
# Show register template
return render_template('register.html', buy_licence_link=buy_licence_link, ERROR_MESSAGE="")
@app.route('/register', methods=['POST'])
def register_post():
buy_licence_link = os.getenv('BUY_LICENCE_LINK')
if 'licence' not in request.form:
return render_template('register.html', buy_licence_link=buy_licence_link, ERROR_MESSAGE="No licence key provided")
licence_key = request.form['licence']
# Check if licence key is valid
key_file = open('/data/licence_key.txt', 'r')
valid_key = False
for line in key_file.readlines():
if licence_key == line.strip('\n'):
valid_key = True
break
key_file.close()
if not valid_key:
return render_template('register.html', buy_licence_link=buy_licence_link, ERROR_MESSAGE="Invalid licence key")
# Get domain
domain = request.form['domain']
if domain == None:
return render_template('register.html', buy_licence_link=buy_licence_link, ERROR_MESSAGE="No domain provided")
# Check if domain already exists
if site_exists(domain):
return render_template('register.html', buy_licence_link=buy_licence_link, ERROR_MESSAGE="Domain already exists")
# Check if domain contains http:// or https://
if domain.startswith("http://") or domain.startswith("https://"):
return render_template('register.html', buy_licence_link=buy_licence_link, ERROR_MESSAGE="Domain should not contain http:// or https://")
# Set domain to lowercase
domain = domain.lower()
# Check if worker file exists
workers = None
try:
licences_file = open('/data/licence_key.txt', 'r')
licences = licences_file.readlines()
licences_file.close()
worker_file = open('/data/workers.txt', 'r')
workers = worker_file.readlines()
worker_file.close()
except FileNotFoundError:
pass
return render_template('register.html', buy_licence_link=buy_licence_link, ERROR_MESSAGE="No workers available\nPlease contact support")
# Create html page
html = "<h1>Welcome</h1><br>"
html += "<h2>Create a site</h2>"
html += "<form action='/add-site' method='POST'>"
html += "<p>Domain: <input type='text' name='domain'></p>"
html += "<p>Licence key: <input type='text' name='licence'></p>"
html += "<input type='submit' value='Create site'>"
html += "</form>"
# Get a worker that has available slots
worker = None
for line in workers:
if not line.__contains__(':'):
continue
ip = line.split(':')[1].strip('\n')
resp=requests.get("http://"+ip + ":5000/status",timeout=2)
if (resp.status_code == 200):
if resp.json()['availability'] == True:
worker = line
break
if worker == None:
return render_template('register.html', buy_licence_link=buy_licence_link, ERROR_MESSAGE="No workers available\nPlease contact support")
# Delete licence key
key_file = open('/data/licence_key.txt', 'r')
lines = key_file.readlines()
key_file.close()
key_file = open('/data/licence_key.txt', 'w')
for line in lines:
if line.strip("\n") != licence_key:
key_file.write(line)
key_file.close()
# Add domain to file
sites_file = open('/data/sites.txt', 'a')
sites_file.write(domain + ':' + worker.split(':')[0] + '\n')
sites_file.close()
# Send worker request
requests.post("http://"+ worker.split(':')[1].strip('\n') + ":5000/new-site?domain=" + domain)
return redirect('/success?domain=' + domain + '&status=creating')
@app.route('/success')
def success():
if 'domain' not in request.args:
return redirect('/')
domain = request.args.get('domain')
domain = domain.lower()
if not site_exists(domain):
return render_template('success.html', message="Error: Domain does not exist\nPlease contact support")
if 'status' not in request.args:
# Get worker
worker = site_worker(domain)
if worker == None:
return render_template('success.html', message="Error: Domain does not exist\nPlease contact support")
# Get worker ip
ip = workerIP_PRIV(worker)
# Get TLSA record
resp=requests.get("http://"+ip + ":5000/tlsa?domain=" + domain,timeout=2)
json = resp.json()
publicIP = workerIP(worker)
if "tlsa" in json:
tlsa = json['tlsa']
return render_template('success.html', message="Success\nDomain: " + domain + "\nIP: " + publicIP + "\nTLSA: " + tlsa + "\nMake sure to add the TLSA record to `_443._tcp." + domain + "` or `*." + domain + "`")
else:
return render_template('success.html', message="Success\nDomain: " + domain + "\nIP: " + publicIP + "\nTLSA: Pending\nNo TLSA record found")
elif request.args.get('status') == 'creating':
return render_template('success.html')
@app.route('/site-count')
def site_count_route():
return str(get_sites_count())
html += "<br><h2>Stats</h2><br>"
html += "<h2>Workers</h2>"
html += "<p>Number of workers: " + str(len(workers)) + "</p>"
html += "<p>Workers:</p>"
html += "<ul>"
for worker in workers:
html += "<li>Name: " + worker.split(':')[0] + " | IP " + worker.split(':')[2].strip('\n') + "</li>"
html += "</ul>"
html += "<h2>Sites</h2>"
html += "<p>Number of sites: " + str(len(sites)) + "</p>"
html += "<p>Sites:</p>"
html += "<ul>"
for site in sites:
html += "<li>Domain: " + site.split(':')[0] + " | Worker: " + site.split(':')[1].strip('\n') + "</li>"
html += "</ul>"
html += "<h2>Licences</h2>"
html += "<p>Number of licences: " + str(len(licences)) + "</p>"
html += "<h2><a href='/admin'>Admin</a></h2>"
return html
# Admin page
@app.route('/admin')
@@ -641,7 +721,7 @@ def addsite():
if domain.startswith("http://") or domain.startswith("https://"):
return jsonify({'error': 'Domain should not contain http:// or https://', 'success': 'false'})
domain = domain.lower()
# Check if worker file exists
workers = None
try:
@@ -780,6 +860,10 @@ def login():
def failed_login():
return "<h1>Failed login</h1><br><form action='/login' method='POST'><input type='password' name='password'><input type='submit' value='Login'></form>"
# Assets
@app.route('/assets/<path:path>')
def send_report(path):
return send_from_directory('templates/assets', path)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

View File

@@ -0,0 +1,61 @@
(function() {
"use strict"; // Start of use strict
function initParallax() {
if (!('requestAnimationFrame' in window)) return;
if (/Mobile|Android/.test(navigator.userAgent)) return;
var parallaxItems = document.querySelectorAll('[data-bss-parallax]');
if (!parallaxItems.length) return;
var defaultSpeed = 0.5;
var visible = [];
var scheduled;
window.addEventListener('scroll', scroll);
window.addEventListener('resize', scroll);
scroll();
function scroll() {
visible.length = 0;
for (var i = 0; i < parallaxItems.length; i++) {
var rect = parallaxItems[i].getBoundingClientRect();
var speed = parseFloat(parallaxItems[i].getAttribute('data-bss-parallax-speed'), 10) || defaultSpeed;
if (rect.bottom > 0 && rect.top < window.innerHeight) {
visible.push({
speed: speed,
node: parallaxItems[i]
});
}
}
cancelAnimationFrame(scheduled);
if (visible.length) {
scheduled = requestAnimationFrame(update);
}
}
function update() {
for (var i = 0; i < visible.length; i++) {
var node = visible[i].node;
var speed = visible[i].speed;
node.style.transform = 'translate3d(0, ' + (-window.scrollY * speed) + 'px, 0)';
}
}
}
initParallax();
})(); // End of use strict

View File

@@ -0,0 +1,10 @@
// Refresh page without status arg
// Wait 10 seconds
setTimeout(function() {
// Refresh page
// Get domain from param
var domain = urlParams.get('domain');
window.location = "https://hnshosting.au/success?domain=" + domain;
}, 10000);

173
master/templates/index.html Normal file
View File

@@ -0,0 +1,173 @@
<!DOCTYPE html>
<html data-bs-theme="dark" lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>Home - HNSHosting</title>
<link rel="canonical" href="https://wp.hnshosting.au/">
<meta property="og:url" content="https://wp.hnshosting.au/">
<meta name="description" content="HNS Hosting Wordpress">
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "WebSite",
"name": "HNSHosting",
"url": "https://wp.hnshosting.au"
}
</script>
<link rel="icon" type="image/png" sizes="508x430" href="assets/img/favicon.png">
<link rel="icon" type="image/png" sizes="508x430" href="assets/img/favicon.png">
<link rel="icon" type="image/png" sizes="508x430" href="assets/img/favicon.png">
<link rel="icon" type="image/png" sizes="508x430" href="assets/img/favicon.png">
<link rel="icon" type="image/png" sizes="508x430" href="assets/img/favicon.png">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800&amp;display=swap">
</head>
<body>
<nav class="navbar navbar-expand-md sticky-top py-3 navbar-dark" id="mainNav">
<div class="container"><a class="navbar-brand d-flex align-items-center" href="/"><span class="bs-icon-sm bs-icon-circle bs-icon-primary shadow d-flex justify-content-center align-items-center me-2 bs-icon" style="background: transparent;"><img src="assets/img/favicon.png" style="width: 100%;"></span><span>HNSHosting</span></a><button data-bs-toggle="collapse" class="navbar-toggler" data-bs-target="#navcol-1"><span class="visually-hidden">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
<div class="collapse navbar-collapse" id="navcol-1">
<ul class="navbar-nav mx-auto">
<li class="nav-item"><a class="nav-link active" href="/">Home</a></li>
<li class="nav-item"><a class="nav-link active" href="/#contact">Contact</a></li>
<li class="nav-item"><a class="nav-link" href="register">Register Site</a></li>
</ul>
</div>
</div>
</nav>
<header class="bg-dark">
<div class="container pt-4 pt-xl-5">
<div class="row pt-5">
<div class="col-md-8 col-xl-6 text-center text-md-start mx-auto">
<div class="text-center">
<h1 class="fw-bold">The best solution for your Handshake domain</h1>
</div>
<p class="text-center" style="padding-bottom: 50px;padding-top: 25px;">Wordpress allows you to have an easily customizable website on your Handshake domain.</p>
<p class="text-center" style="font-size: 22px;">Currently hosting {{site_count}} sites!</p>
</div>
</div>
</div>
</header>
<section style="background: rgb(39,38,46);">
<div class="container bg-dark py-5" style="background: rgb(39, 38, 46);">
<div class="row">
<div class="col-md-8 col-xl-6 text-center mx-auto">
<p class="fw-bold text-success mb-2">Our Services</p>
<h3 class="fw-bold">What we do for you</h3>
</div>
</div>
<div class="py-5 p-lg-5">
<div class="row row-cols-1 row-cols-md-2 mx-auto" style="max-width: 900px;">
<div class="col mb-5">
<div class="card shadow-sm">
<div class="card-body px-4 py-5 px-md-5">
<div class="bs-icon-lg d-flex justify-content-center align-items-center mb-3 bs-icon" style="top: 1rem;right: 1rem;position: absolute;"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16" class="bi bi-shield-lock text-success">
<path d="M5.338 1.59a61.44 61.44 0 0 0-2.837.856.481.481 0 0 0-.328.39c-.554 4.157.726 7.19 2.253 9.188a10.725 10.725 0 0 0 2.287 2.233c.346.244.652.42.893.533.12.057.218.095.293.118a.55.55 0 0 0 .101.025.615.615 0 0 0 .1-.025c.076-.023.174-.061.294-.118.24-.113.547-.29.893-.533a10.726 10.726 0 0 0 2.287-2.233c1.527-1.997 2.807-5.031 2.253-9.188a.48.48 0 0 0-.328-.39c-.651-.213-1.75-.56-2.837-.855C9.552 1.29 8.531 1.067 8 1.067c-.53 0-1.552.223-2.662.524zM5.072.56C6.157.265 7.31 0 8 0s1.843.265 2.928.56c1.11.3 2.229.655 2.887.87a1.54 1.54 0 0 1 1.044 1.262c.596 4.477-.787 7.795-2.465 9.99a11.775 11.775 0 0 1-2.517 2.453 7.159 7.159 0 0 1-1.048.625c-.28.132-.581.24-.829.24s-.548-.108-.829-.24a7.158 7.158 0 0 1-1.048-.625 11.777 11.777 0 0 1-2.517-2.453C1.928 10.487.545 7.169 1.141 2.692A1.54 1.54 0 0 1 2.185 1.43 62.456 62.456 0 0 1 5.072.56z"></path>
<path d="M9.5 6.5a1.5 1.5 0 0 1-1 1.415l.385 1.99a.5.5 0 0 1-.491.595h-.788a.5.5 0 0 1-.49-.595l.384-1.99a1.5 1.5 0 1 1 2-1.415z"></path>
</svg></div>
<h5 class="fw-bold card-title">Secured over SSL with DANE</h5>
<p class="text-muted card-text mb-4">Anyone with a resolver supporting DANE will be redirected to the HTTPS version on your site and will have an encrypted connection using DANE for verification.</p><a class="btn btn-primary shadow" role="button" target="_blank" href="https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Named_Entities">Learn more</a>
</div>
</div>
</div>
<div class="col mb-5" style="margin-top: 150px;">
<div class="card shadow-sm">
<div class="card-body px-4 py-5 px-md-5">
<div class="bs-icon-lg d-flex justify-content-center align-items-center mb-3 bs-icon" style="top: 1rem;right: 1rem;position: absolute;"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16" class="bi bi-building-lock text-success">
<path d="M2 1a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v6.5a.5.5 0 0 1-1 0V1H3v14h3v-2.5a.5.5 0 0 1 .5-.5H8v4H3a1 1 0 0 1-1-1V1Z"></path>
<path d="M4.5 2a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1Zm2.5.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1Zm3.5-.5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1ZM4 5.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1ZM7.5 5a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1Zm2.5.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1ZM4.5 8a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-1Zm2.5.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1ZM9 13a1 1 0 0 1 1-1v-1a2 2 0 1 1 4 0v1a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-4a1 1 0 0 1-1-1v-2Zm3-3a1 1 0 0 0-1 1v1h2v-1a1 1 0 0 0-1-1Z"></path>
</svg></div>
<h5 class="fw-bold card-title">Hosted with security in mind</h5>
<p class="text-muted card-text mb-4">The worker servers are fully secured so that the only access is HTTP for web traffic.<br>Any terminal access for maintenance is over a VPN tunnel to stop any unauthorized access. All SSH connections send a push notification to the admin's phone to alert him to any access.</p>
</div>
</div>
</div>
<div class="col mb-4" style="margin-top: -150px;">
<div class="card shadow-sm">
<div class="card-body px-4 py-5 px-md-5">
<div class="bs-icon-lg d-flex justify-content-center align-items-center mb-3 bs-icon" style="top: 1rem;right: 1rem;position: absolute;"><svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 24 24" width="1em" fill="currentColor" class="text-success">
<path d="M0 0h24v24H0z" fill="none"></path>
<path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z"></path>
</svg></div>
<h5 class="fw-bold card-title">Regular backups</h5>
<p class="text-muted card-text mb-4">The worker server has regular encrypted backups to an offsite location to allow recovery of any data if the server goes down.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section>
<div class="container py-5">
<div class="mx-auto" style="max-width: 900px;">
<div class="row row-cols-1 row-cols-md-2 d-flex justify-content-center">
<div class="col mb-4">
<div class="card bg-primary-light">
<div class="card-body text-center px-4 py-5 px-md-5">
<p class="fw-bold text-primary card-text mb-2">Fully Managed</p>
<h5 class="fw-bold card-title mb-3">Control over plugins, users, access and everything with your site.</h5>
</div>
</div>
</div>
<div class="col mb-4">
<div class="card bg-secondary-light">
<div class="card-body text-center px-4 py-5 px-md-5">
<p class="fw-bold text-secondary card-text mb-2">Free Licences</p>
<h5 class="fw-bold card-title mb-3">We offer a free tier with 1 GB storage capacity.<br>If you would like more please contact us to find an acceptable price for you.<br>Join our Discord for a free licence</h5>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section id="contact" class="py-5">
<div class="container">
<div class="row mb-5">
<div class="col-md-8 col-xl-6 text-center mx-auto">
<p class="fw-bold text-success mb-2">Contacts</p>
<h2 class="fw-bold">Contact Us</h2>
</div>
</div>
<div class="row d-flex justify-content-center">
<div class="col-md-4 col-xl-4 d-flex justify-content-center justify-content-xl-start">
<div class="d-flex flex-wrap flex-md-column justify-content-md-start align-items-md-start h-100">
<div class="d-flex align-items-center p-3">
<div class="bs-icon-md bs-icon-circle bs-icon-primary shadow d-flex flex-shrink-0 justify-content-center align-items-center d-inline-block bs-icon bs-icon-md"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16" class="bi bi-discord">
<path d="M13.545 2.907a13.227 13.227 0 0 0-3.257-1.011.05.05 0 0 0-.052.025c-.141.25-.297.577-.406.833a12.19 12.19 0 0 0-3.658 0 8.258 8.258 0 0 0-.412-.833.051.051 0 0 0-.052-.025c-1.125.194-2.22.534-3.257 1.011a.041.041 0 0 0-.021.018C.356 6.024-.213 9.047.066 12.032c.001.014.01.028.021.037a13.276 13.276 0 0 0 3.995 2.02.05.05 0 0 0 .056-.019c.308-.42.582-.863.818-1.329a.05.05 0 0 0-.01-.059.051.051 0 0 0-.018-.011 8.875 8.875 0 0 1-1.248-.595.05.05 0 0 1-.02-.066.051.051 0 0 1 .015-.019c.084-.063.168-.129.248-.195a.05.05 0 0 1 .051-.007c2.619 1.196 5.454 1.196 8.041 0a.052.052 0 0 1 .053.007c.08.066.164.132.248.195a.051.051 0 0 1-.004.085 8.254 8.254 0 0 1-1.249.594.05.05 0 0 0-.03.03.052.052 0 0 0 .003.041c.24.465.515.909.817 1.329a.05.05 0 0 0 .056.019 13.235 13.235 0 0 0 4.001-2.02.049.049 0 0 0 .021-.037c.334-3.451-.559-6.449-2.366-9.106a.034.034 0 0 0-.02-.019Zm-8.198 7.307c-.789 0-1.438-.724-1.438-1.612 0-.889.637-1.613 1.438-1.613.807 0 1.45.73 1.438 1.613 0 .888-.637 1.612-1.438 1.612Zm5.316 0c-.788 0-1.438-.724-1.438-1.612 0-.889.637-1.613 1.438-1.613.807 0 1.451.73 1.438 1.613 0 .888-.631 1.612-1.438 1.612Z"></path>
</svg></div>
<div class="px-2">
<h6 class="fw-bold mb-0">Discord</h6>
<p class="text-muted mb-0"><a href="https://l.woodburn.au/discord" target="_blank">Join our server</a></p>
</div>
</div>
<div class="d-flex align-items-center p-3">
<div class="bs-icon-md bs-icon-circle bs-icon-primary shadow d-flex flex-shrink-0 justify-content-center align-items-center d-inline-block bs-icon bs-icon-md"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16" class="bi bi-envelope">
<path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4Zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2Zm13 2.383-4.708 2.825L15 11.105V5.383Zm-.034 6.876-5.64-3.471L8 9.583l-1.326-.795-5.64 3.47A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.741ZM1 11.105l4.708-2.897L1 5.383v5.722Z"></path>
</svg></div>
<div class="px-2">
<h6 class="fw-bold mb-0">Email</h6>
<p class="text-muted mb-0"><a href="mailto:hosting@nathan.woodburn.au">hosting@nathan.woodburn.au</a></p>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<footer class="bg-dark">
<div class="container py-4 py-lg-5">
<hr>
<div class="text-muted d-flex justify-content-between align-items-center pt-3">
<p class="mb-0">Copyright © 2023 HNSHosting</p>
</div>
</div>
</footer>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/bold-and-dark.js"></script>
</body>
</html>

View File

@@ -0,0 +1,70 @@
<!DOCTYPE html>
<html data-bs-theme="dark" lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>Sign up - HNSHosting</title>
<link rel="canonical" href="https://wp.hnshosting.au/register.html">
<meta property="og:url" content="https://wp.hnshosting.au/register.html">
<meta name="description" content="HNS Hosting Wordpress">
<link rel="icon" type="image/png" sizes="508x430" href="assets/img/favicon.png">
<link rel="icon" type="image/png" sizes="508x430" href="assets/img/favicon.png">
<link rel="icon" type="image/png" sizes="508x430" href="assets/img/favicon.png">
<link rel="icon" type="image/png" sizes="508x430" href="assets/img/favicon.png">
<link rel="icon" type="image/png" sizes="508x430" href="assets/img/favicon.png">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800&amp;display=swap">
</head>
<body>
<nav class="navbar navbar-expand-md sticky-top py-3 navbar-dark" id="mainNav">
<div class="container"><a class="navbar-brand d-flex align-items-center" href="/"><span class="bs-icon-sm bs-icon-circle bs-icon-primary shadow d-flex justify-content-center align-items-center me-2 bs-icon" style="background: transparent;"><img src="assets/img/favicon.png" style="width: 100%;"></span><span>HNSHosting</span></a><button data-bs-toggle="collapse" class="navbar-toggler" data-bs-target="#navcol-1"><span class="visually-hidden">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
<div class="collapse navbar-collapse" id="navcol-1">
<ul class="navbar-nav mx-auto">
<li class="nav-item"><a class="nav-link" href="/">Home</a></li>
<li class="nav-item"><a class="nav-link" href="/#contact">Contact</a></li>
<li class="nav-item"><a class="nav-link" href="register">Register Site</a></li>
</ul>
</div>
</div>
</nav>
<section class="py-5">
<div class="container py-5">
<div class="row mb-4 mb-lg-5">
<div class="col-md-8 col-xl-6 text-center mx-auto">
<p class="fw-bold text-success mb-2">Register site</p>
<h2 class="fw-bold">Get started with your Hosting here.</h2>
</div>
</div>
<div class="row d-flex justify-content-center">
<div class="col-md-6 col-xl-4">
<div class="card">
<div class="card-body text-center d-flex flex-column align-items-center">
<form method="post" action="/register">
<div class="mb-3"><input type="text" name="domain" placeholder="Domain"></div>
<div class="mb-3"><input type="text" placeholder="Licence Key" name="licence"></div>
<div class="mb-3">
<p style="color: rgb(255,0,0);">{{ERROR_MESSAGE}}</p><button class="btn btn-primary shadow d-block w-100" type="submit">Create site</button>
</div>
<p class="text-muted">Don't have a licence?<br><a href="{{buy_licence_link}}" target="_blank">Click here to buy one</a></p>
</form>
</div>
</div>
</div>
</div>
</div>
</section>
<footer class="bg-dark">
<div class="container py-4 py-lg-5">
<hr>
<div class="text-muted d-flex justify-content-between align-items-center pt-3">
<p class="mb-0">Copyright © 2023 HNSHosting</p>
</div>
</div>
</footer>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/bold-and-dark.js"></script>
</body>
</html>

View File

@@ -0,0 +1,58 @@
<!DOCTYPE html>
<html data-bs-theme="dark" lang="en" style="height: 100%;">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>Home - HNSHosting</title>
<link rel="canonical" href="https://wp.hnshosting.au/success.html">
<meta property="og:url" content="https://wp.hnshosting.au/success.html">
<meta name="description" content="HNS Hosting Wordpress">
<link rel="icon" type="image/png" sizes="508x430" href="assets/img/favicon.png">
<link rel="icon" type="image/png" sizes="508x430" href="assets/img/favicon.png">
<link rel="icon" type="image/png" sizes="508x430" href="assets/img/favicon.png">
<link rel="icon" type="image/png" sizes="508x430" href="assets/img/favicon.png">
<link rel="icon" type="image/png" sizes="508x430" href="assets/img/favicon.png">
<link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800&amp;display=swap">
</head>
<body style="height: 100%;">
<nav class="navbar navbar-expand-md sticky-top py-3 navbar-dark" id="mainNav">
<div class="container"><a class="navbar-brand d-flex align-items-center" href="/"><span class="bs-icon-sm bs-icon-circle bs-icon-primary shadow d-flex justify-content-center align-items-center me-2 bs-icon" style="background: transparent;"><img src="assets/img/favicon.png" style="width: 100%;"></span><span>HNSHosting</span></a><button data-bs-toggle="collapse" class="navbar-toggler" data-bs-target="#navcol-1"><span class="visually-hidden">Toggle navigation</span><span class="navbar-toggler-icon"></span></button>
<div class="collapse navbar-collapse" id="navcol-1">
<ul class="navbar-nav mx-auto">
<li class="nav-item"><a class="nav-link" href="/">Home</a></li>
<li class="nav-item"><a class="nav-link" href="/#contact">Contact</a></li>
<li class="nav-item"><a class="nav-link" href="register">Register Site</a></li>
</ul>
</div>
</div>
</nav>
<header class="bg-dark" style="height: 75%;">
<div class="container pt-4 pt-xl-5">
<div class="row pt-5" style="height: 100%;">
<div class="col-md-8 col-xl-6 text-center text-md-start mx-auto">
<div class="text-center">
<p class="fw-bold text-success mb-2">Success</p>
<h1 class="fw-bold">Your site is installing.<br>Please wait...</h1>
</div>
<p class="text-center">{{message}}</p>
</div>
</div>
</div>
</header>
<footer class="bg-dark">
<div class="container py-4 py-lg-5">
<hr>
<div class="text-muted d-flex justify-content-between align-items-center pt-3">
<p class="mb-0">Copyright © 2023 HNSHosting</p>
</div>
</div>
</footer>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/bold-and-dark.js"></script>
<script src="assets/js/status_update.js"></script>
</body>
</html>

View File

@@ -24,6 +24,21 @@ python3 -m pip install -r requirements.txt
cp .env.example .env
chmod +x wp.sh tlsa.sh
# Add proxy to docker
mkdir ~/.docker
echo """{
\"proxies\": {
\"default\": {
\"httpProxy\": \"http://proxy.hnsproxy.au:80\",
\"httpsProxy\": \"https://proxy.hnsproxy.au:443\",
\"noProxy\": \"localhost\"
}
}
}""" > ~/.docker/config.json
# Restart docker
sudo systemctl restart docker
# Pull docker images to save time later
docker pull mysql:5.7 &
docker pull wordpress:latest &

View File

@@ -56,9 +56,11 @@ services:
WORDPRESS_DB_PASSWORD: $MYSQL_PASSWORD
WORDPRESS_DB_NAME: WordPressDatabase
volumes:
[\"./:/var/www/html\"]
- data:/var/www/html
volumes:
mysql: {}
mysql:
data:
""" > docker-compose.yml
# Start the containers