140 Commits

Author SHA1 Message Date
752efbfc3f fix: Use strip not trim
All checks were successful
Build Docker / Build_Master_AMD (push) Successful in 1m14s
Build Docker / Build_Master_ARM (push) Successful in 1m16s
Build Docker / Build_Bot_ARM (push) Successful in 1m34s
Build Docker / Build_Bot_AMD (push) Successful in 2m53s
2025-06-03 12:02:35 +10:00
04e1335173 fix: Add more strict domain checking
All checks were successful
Build Docker / Build_Master_AMD (push) Successful in 1m13s
Build Docker / Build_Master_ARM (push) Successful in 1m15s
Build Docker / Build_Bot_ARM (push) Successful in 1m43s
Build Docker / Build_Bot_AMD (push) Successful in 3m18s
2025-04-22 18:54:57 +10:00
58624e152e fix: Remove any trailing period or slash
All checks were successful
Build Docker / Build_Bot_ARM (push) Successful in 24s
Build Docker / Build_Master_ARM (push) Successful in 25s
Build Docker / Build_Master_AMD (push) Successful in 54s
Build Docker / Build_Bot_AMD (push) Successful in 1m59s
2024-07-19 15:47:10 +10:00
4f8d80f3b6 fix: Template for domain info page error
All checks were successful
Build Docker / Build_Master_ARM (push) Successful in 23s
Build Docker / Build_Bot_ARM (push) Successful in 21s
Build Docker / Build_Bot_AMD (push) Successful in 31s
Build Docker / Build_Master_AMD (push) Successful in 36s
2024-07-12 21:50:59 +10:00
41cafd1a95 feat: Add AMD build
All checks were successful
Build Docker / Build_Master_AMD (push) Successful in 1m0s
Build Docker / Build_Master_ARM (push) Successful in 1m13s
Build Docker / Build_Bot_ARM (push) Successful in 1m33s
Build Docker / Build_Bot_AMD (push) Successful in 2m52s
2024-07-12 21:36:58 +10:00
6ff40bff0e feat: Update analytics
All checks were successful
Build Docker / Build Bot (push) Successful in 26s
Build Docker / Build Master (push) Successful in 29s
2024-02-23 17:46:03 +11:00
d0ebdab064 fix: Typo in info page
All checks were successful
Build Docker / Build Bot (push) Successful in 26s
Build Docker / Build Master (push) Successful in 27s
2024-02-23 11:04:29 +11:00
00f677e9ee fix: Discord link in register page
All checks were successful
Build Docker / Build Master (push) Successful in 1m13s
Build Docker / Build Bot (push) Successful in 1m30s
2024-02-14 11:56:45 +11:00
3da15dffa2 feat: Add analytics
All checks were successful
Build Docker / Build Bot (push) Successful in 25s
Build Docker / Build Master (push) Successful in 35s
2023-12-13 14:56:18 +11:00
412366af2f feat: Add new email address for support
All checks were successful
Build Docker / Build Master (push) Successful in 1m11s
Build Docker / Build Bot (push) Successful in 1m35s
2023-12-04 15:04:43 +11:00
58c6f8027e feat: Add discord link to register page
All checks were successful
Build Docker / Build Bot (push) Successful in 21s
Build Docker / Build Master (push) Successful in 23s
2023-11-17 17:12:12 +11:00
086bab83d3 feat: Add terms and 404 pages
All checks were successful
Build Docker / Build Bot (push) Successful in 20s
Build Docker / Build Master (push) Successful in 25s
2023-11-17 17:01:14 +11:00
0988333f3b feat: Use alias for hardcoded IPs
All checks were successful
Build Docker / Build Master (push) Successful in 22s
Build Docker / Build Bot (push) Successful in 24s
2023-11-08 12:06:07 +11:00
9d06151ed2 feat: Only send WP licence email on subscription start
All checks were successful
Build Docker / Build Master (push) Successful in 22s
Build Docker / Build Bot (push) Successful in 22s
2023-11-02 16:36:32 +11:00
63ee2aa82b Merge branch 'develop' into main
All checks were successful
Build Docker / Build Master (push) Successful in 30s
Build Docker / Build Bot (push) Successful in 29s
2023-10-23 15:46:25 +11:00
49acea31ac feat: Add instructions for enabling HIP2 on WordPress site
All checks were successful
Build Docker / Build Master (push) Successful in 26s
Build Docker / Build Bot (push) Successful in 25s
This commit adds detailed instructions for enabling HIP2 on a WordPress site. It includes steps to download, upload, and activate the HIP2 plugin, as well as setting the HNS wallet address and testing the functionality.
2023-10-23 15:46:16 +11:00
6b855a5b29 fix: Fix wordpress rewrites for hip2
All checks were successful
Build Docker / Build Master (push) Successful in 1m6s
Build Docker / Build Bot (push) Successful in 1m29s
2023-10-23 15:42:38 +11:00
9d57b8f858 main: Update admin page
All checks were successful
Build Docker / Build Master (push) Successful in 23s
Build Docker / Build Bot (push) Successful in 22s
2023-09-25 15:14:16 +10:00
6d9ba77568 main: Fix return for info page
All checks were successful
Build Docker / Build Master (push) Successful in 25s
Build Docker / Build Bot (push) Successful in 24s
2023-09-25 15:07:56 +10:00
9c5b00433f bot: Adding a few catches to the bot
All checks were successful
Build Docker / Build Master (push) Successful in 42s
Build Docker / Build Bot (push) Successful in 1m24s
2023-09-21 11:32:34 +10:00
e241f6ffeb main: Add return to info page
All checks were successful
Build Docker / Build Master (push) Successful in 22s
Build Docker / Build Bot (push) Successful in 22s
2023-09-20 22:33:09 +10:00
188334c850 main: Updated refresh script
All checks were successful
Build Docker / Build Master (push) Successful in 24s
Build Docker / Build Bot (push) Successful in 23s
2023-09-20 22:32:27 +10:00
6ea4e72e8a main: Add style to tlsa
All checks were successful
Build Docker / Build Bot (push) Successful in 22s
Build Docker / Build Master (push) Successful in 24s
2023-09-20 22:29:35 +10:00
56c7fcd617 main: Use the success page for info page
All checks were successful
Build Docker / Build Master (push) Successful in 24s
Build Docker / Build Bot (push) Successful in 23s
2023-09-20 22:26:34 +10:00
c9f8a8237d main: Add code block for tlsa info
All checks were successful
Build Docker / Build Bot (push) Successful in 21s
Build Docker / Build Master (push) Successful in 25s
2023-09-20 22:21:00 +10:00
bda99dbf5f main: Updated status page style
All checks were successful
Build Docker / Build Bot (push) Successful in 22s
Build Docker / Build Master (push) Successful in 24s
2023-09-20 22:11:58 +10:00
08f36a7a50 worker: Update wp script to use named volume for db
All checks were successful
Build Docker / Build Master (push) Successful in 26s
Build Docker / Build Bot (push) Successful in 26s
2023-09-20 22:01:01 +10:00
94ebacd84d Merge branch 'develop' into main
All checks were successful
Build Docker / Build Bot (push) Successful in 25s
Build Docker / Build Master (push) Successful in 26s
2023-09-18 14:56:15 +10:00
6f86987901 bot: Fix typo with variables
All checks were successful
Build Docker / Build Master (push) Successful in 19s
Build Docker / Build Bot (push) Successful in 21s
2023-09-18 14:49:22 +10:00
910ce1b098 bot: Display site count in bot status
All checks were successful
Build Docker / Build Master (push) Successful in 20s
Build Docker / Build Bot (push) Successful in 22s
2023-09-18 14:47:14 +10:00
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
8f5f8df0aa Merge branch 'develop' into main
All checks were successful
Build Docker / Build Bot (push) Successful in 27s
Build Docker / Build Master (push) Successful in 28s
2023-09-02 14:15:03 +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
7729ea62b3 Merge branch 'develop' into main
All checks were successful
Build Docker / Build Master (push) Successful in 24s
Build Docker / Build Bot (push) Successful in 23s
Build Docker for Release / Build Master (push) Successful in 35s
Build Docker for Release / Build Bot (push) Successful in 34s
2023-08-25 18:26:43 +10:00
457a57739a Merge branch 'feature/dashboard' into develop
All checks were successful
Build Docker / Build Master (push) Successful in 25s
Build Docker / Build Bot (push) Successful in 24s
2023-08-25 18:25:04 +10:00
67ed81fd2e main: Added info link to domains in admin page
All checks were successful
Build Docker / Build Bot (push) Successful in 21s
Build Docker / Build Master (push) Successful in 27s
2023-08-25 18:22:20 +10:00
2ef8e2c38d main: Fixed reused function name
All checks were successful
Build Docker / Build Bot (push) Successful in 24s
Build Docker / Build Master (push) Successful in 26s
2023-08-25 18:17:12 +10:00
c8eafb6406 main: Updated domain info page
All checks were successful
Build Docker / Build Bot (push) Successful in 27s
Build Docker / Build Master (push) Successful in 28s
2023-08-25 18:13:36 +10:00
73d11a0f76 main: Fixed customer side
All checks were successful
Build Docker / Build Bot (push) Successful in 26s
Build Docker / Build Master (push) Successful in 28s
2023-08-25 18:01:49 +10:00
3628e0a4ac main: Added customer self service
All checks were successful
Build Docker / Build Bot (push) Successful in 22s
Build Docker / Build Master (push) Successful in 28s
2023-08-25 17:57:51 +10:00
20dbf6c0df main: Fixed a few bits of the admin panel
All checks were successful
Build Docker / Build Bot (push) Successful in 21s
Build Docker / Build Master (push) Successful in 27s
2023-08-25 17:52:17 +10:00
8a2cad16ec main: Fixed typo
All checks were successful
Build Docker / Build Master (push) Successful in 27s
Build Docker / Build Bot (push) Successful in 26s
2023-08-25 17:48:42 +10:00
48330f7ef9 main: Added licence and site creation for admin
All checks were successful
Build Docker / Build Bot (push) Successful in 24s
Build Docker / Build Master (push) Successful in 27s
2023-08-25 17:45:46 +10:00
7703bfa4d5 main: Catch for offline worker
All checks were successful
Build Docker / Build Bot (push) Successful in 22s
Build Docker / Build Master (push) Successful in 28s
2023-08-25 17:31:32 +10:00
ba96f9b84b main: Added new worker admin
All checks were successful
Build Docker / Build Master (push) Successful in 28s
Build Docker / Build Bot (push) Successful in 27s
2023-08-25 17:18:37 +10:00
0a33a6150d main: Fixed worker info
All checks were successful
Build Docker / Build Bot (push) Successful in 26s
Build Docker / Build Master (push) Successful in 27s
2023-08-25 17:13:34 +10:00
c9be5cedcb main: Initial admin page
All checks were successful
Build Docker / Build Bot (push) Successful in 27s
Build Docker / Build Master (push) Successful in 29s
2023-08-25 17:07:44 +10:00
1fb2493848 main: Updated form
All checks were successful
Build Docker / Build Bot (push) Successful in 20s
Build Docker / Build Master (push) Successful in 26s
2023-08-25 16:51:19 +10:00
9853214d83 main: Add failed login page
All checks were successful
Build Docker / Build Bot (push) Successful in 22s
Build Docker / Build Master (push) Successful in 28s
2023-08-25 16:47:22 +10:00
843d2d12a0 main: Fixed login typo
All checks were successful
Build Docker / Build Bot (push) Successful in 25s
Build Docker / Build Master (push) Successful in 26s
2023-08-25 16:38:34 +10:00
8f962804a4 main: Login fixes
All checks were successful
Build Docker / Build Bot (push) Successful in 25s
Build Docker / Build Master (push) Successful in 27s
2023-08-25 16:36:53 +10:00
9e485265af main: Added the post method
All checks were successful
Build Docker / Build Bot (push) Successful in 24s
Build Docker / Build Master (push) Successful in 26s
2023-08-25 16:32:50 +10:00
83bde4b218 main: Added admin page
All checks were successful
Build Docker / Build Bot (push) Successful in 21s
Build Docker / Build Master (push) Successful in 27s
2023-08-25 16:29:25 +10:00
52fca38af9 main: Added return to dash
All checks were successful
Build Docker / Build Bot (push) Successful in 20s
Build Docker / Build Master (push) Successful in 26s
2023-08-25 16:07:25 +10:00
4db44bb99e actions: Try run on feature branch
All checks were successful
Build Docker / Build Bot (push) Successful in 26s
Build Docker / Build Master (push) Successful in 27s
2023-08-25 16:03:45 +10:00
0e2ad55eb7 Revert "actions: Attempt to fix"
This reverts commit 0c20572369.
2023-08-25 16:01:30 +10:00
fca523f013 Revert "actions: Fix branch rule"
All checks were successful
Build Docker / Build Master (push) Successful in 28s
Build Docker / Build Bot (push) Successful in 27s
This reverts commit 4482f85ded.
2023-08-25 15:59:08 +10:00
4482f85ded actions: Fix branch rule 2023-08-25 15:54:58 +10:00
cd598cce47 Merge branch 'develop' into main 2023-08-25 15:54:41 +10:00
0c20572369 actions: Attempt to fix 2023-08-25 15:53:55 +10:00
d2e31bb684 main: Initial dashboard 2023-08-25 15:51:57 +10:00
bbe70647d7 docs: Added info on free mode
All checks were successful
Build Docker / Build Master (push) Successful in 23s
Build Docker / Build Bot (push) Successful in 27s
2023-08-25 14:26:59 +10:00
d6dffc0464 main: Small fixed for licences
All checks were successful
Build Docker / Build Master (push) Successful in 23s
Build Docker / Build Bot (push) Successful in 25s
2023-08-25 14:20:58 +10:00
fb9295c260 bot: Made licence an optional arg
All checks were successful
Build Docker / Build Master (push) Successful in 20s
Build Docker / Build Bot (push) Successful in 24s
2023-08-25 14:17:12 +10:00
c4ae4561e3 main: Cleared up invalid licence response
All checks were successful
Build Docker / Build Bot (push) Successful in 25s
Build Docker / Build Master (push) Successful in 26s
2023-08-25 14:13:29 +10:00
2902624637 bot: Fix to enable free licences of FREE MODE
All checks were successful
Build Docker / Build Master (push) Successful in 21s
Build Docker / Build Bot (push) Successful in 25s
2023-08-25 14:09:26 +10:00
5049796d07 bot: Added free mode
All checks were successful
Build Docker / Build Master (push) Successful in 21s
Build Docker / Build Bot (push) Successful in 24s
2023-08-25 14:01:36 +10:00
5efe4860fc actions: Fix syntax
All checks were successful
Build Docker for Release / Build Master (push) Successful in 24s
Build Docker for Release / Build Bot (push) Successful in 24s
Build Docker / Build Master (push) Successful in 29s
Build Docker / Build Bot (push) Successful in 27s
2023-08-25 13:55:31 +10:00
499a7e348b Merge branch 'develop' into main
All checks were successful
Build Docker / Build Master (push) Successful in 23s
Build Docker / Build Bot (push) Successful in 21s
2023-08-25 13:53:58 +10:00
ed94263050 actions: Don't run dev action when tag is pushed
All checks were successful
Build Docker / Build Master (push) Successful in 25s
Build Docker / Build Bot (push) Successful in 23s
2023-08-25 13:53:28 +10:00
4841344d63 actions: Finished adding release
All checks were successful
Build Docker / Build Master (push) Successful in 26s
Build Docker / Build Bot (push) Successful in 26s
2023-08-25 13:48:39 +10:00
51bcdda5d4 actions: Initial release job
All checks were successful
Build Docker / Build Bot (push) Successful in 21s
Build Docker / Build Master (push) Successful in 23s
Build Docker for Release / TEST (push) Successful in 5s
2023-08-25 13:44:13 +10:00
b38de6ad52 actions: Use same numbering on bot deployment
All checks were successful
Build Docker / Build Bot (push) Successful in 21s
Build Docker / Build Master (push) Successful in 23s
2023-08-25 13:39:26 +10:00
b642cf7269 actions: Try using the actions run variable
All checks were successful
Build Docker / Build Master (push) Successful in 24s
Build Docker / Build Bot (push) Successful in 22s
2023-08-25 13:37:24 +10:00
3e3c2fe61e actions: Test 4 change numbering
All checks were successful
Build Docker / Build Bot (push) Successful in 23s
Build Docker / Build Master (push) Successful in 25s
2023-08-25 13:28:06 +10:00
04edb8b456 actions: Test 3 change numbering
Some checks failed
Build Docker / Build Master (push) Failing after 21s
Build Docker / Build Bot (push) Successful in 27s
2023-08-25 13:26:41 +10:00
45c1ea3557 actions: Test 2 change numbering
All checks were successful
Build Docker / Build Bot (push) Successful in 22s
Build Docker / Build Master (push) Successful in 25s
2023-08-25 13:25:00 +10:00
778c1b3d92 actions: Change numbering
All checks were successful
Build Docker / Build Bot (push) Successful in 28s
Build Docker / Build Master (push) Successful in 29s
2023-08-25 13:21:24 +10:00
19806b7b1b Merge branch 'feature/send_info_on_ready' into develop
All checks were successful
Build Docker / Build Master (push) Successful in 26s
Build Docker / Build Bot (push) Successful in 26s
2023-08-25 12:59:19 +10:00
908a4e0422 bot: Check for install every 5 seconds
All checks were successful
Build Docker / Build Master (push) Successful in 22s
Build Docker / Build Bot (push) Successful in 26s
2023-08-25 12:54:31 +10:00
d217309e74 bot: Fixed check if site ready function args
All checks were successful
Build Docker / Build Master (push) Successful in 21s
Build Docker / Build Bot (push) Successful in 24s
2023-08-25 12:51:58 +10:00
ce8827ed97 worker: Install missing update repo
All checks were successful
Build Docker / Build Bot (push) Successful in 24s
Build Docker / Build Master (push) Successful in 25s
2023-08-25 12:49:29 +10:00
3b914abf7a bot: Send a dm with the site info when the site is ready
All checks were successful
Build Docker / Build Master (push) Successful in 23s
Build Docker / Build Bot (push) Successful in 26s
2023-08-25 12:46:08 +10:00
3266dbafa9 Merge branch 'develop' into main
All checks were successful
Build Docker / Build Master (push) Successful in 26s
Build Docker / Build Bot (push) Successful in 25s
2023-08-25 12:36:40 +10:00
d7c6e1cf70 docs: Cleared up some info
All checks were successful
Build Docker / Build Master (push) Successful in 24s
Build Docker / Build Bot (push) Successful in 22s
2023-08-25 12:36:23 +10:00
dbbb60cab8 bot: Add private ip to new worker command
All checks were successful
Build Docker / Build Bot (push) Successful in 27s
Build Docker / Build Master (push) Successful in 27s
2023-08-25 12:26:26 +10:00
f54d805371 main: Initial private ip for api 2023-08-25 12:25:23 +10:00
b56ece2216 Merge branch 'develop' into main
All checks were successful
Build Docker / Build Bot (push) Successful in 25s
Build Docker / Build Master (push) Successful in 25s
2023-08-25 12:14:06 +10:00
6eef78a48f docs: Added more info to readme
All checks were successful
Build Docker / Build Bot (push) Successful in 25s
Build Docker / Build Master (push) Successful in 26s
2023-08-25 12:13:24 +10:00
7cddc059b5 worker: Fixed count sites function
All checks were successful
Build Docker / Build Bot (push) Successful in 25s
Build Docker / Build Master (push) Successful in 26s
2023-08-25 11:56:06 +10:00
dd4d97ffc9 main: Fixed list workers 2023-08-25 11:55:51 +10:00
6d28cf7431 main: Fixed newlines in worker file
All checks were successful
Build Docker / Build Bot (push) Successful in 23s
Build Docker / Build Master (push) Successful in 25s
2023-08-25 11:42:31 +10:00
287567a513 worker: Stop install script prompting to install kernel updates 2023-08-25 11:35:22 +10:00
8e9055dcd3 worker: Added pulling docker images to install 2023-08-25 11:35:04 +10:00
0383b47b8e Merge branch 'develop' into main
All checks were successful
Build Docker / Build Bot (push) Successful in 21s
Build Docker / Build Master (push) Successful in 23s
2023-08-24 18:36:46 +10:00
37158f410e actions: Fixed main branch detect
All checks were successful
Build Docker / Build Bot (push) Successful in 22s
Build Docker / Build Master (push) Successful in 24s
2023-08-24 18:35:41 +10:00
fd3e9ba760 worker: Added auto https redirect
All checks were successful
Build Docker / Build Master (push) Successful in 26s
Build Docker / Build Bot (push) Successful in 24s
2023-08-24 18:29:08 +10:00
afd5286ef5 Merge branch 'develop' into main
All checks were successful
Build Docker / Build Master (push) Successful in 22s
Build Docker / Build Bot (push) Successful in 20s
2023-08-24 18:15:16 +10:00
bc1b27a504 worker: Fixed ports
All checks were successful
Build Docker / Build Bot (push) Successful in 23s
Build Docker / Build Master (push) Successful in 25s
2023-08-24 18:15:01 +10:00
d005c5796e actions: Fix errors from feature branches
All checks were successful
Build Docker / Build Master (push) Successful in 27s
Build Docker / Build Bot (push) Successful in 24s
2023-08-24 17:43:02 +10:00
b2f731ce8d actions: Apply fix to bot
All checks were successful
Build Docker / Build Master (push) Successful in 23s
Build Docker / Build Bot (push) Successful in 22s
2023-08-24 17:39:44 +10:00
62770ff0ec actions: syntax error try 3
Some checks failed
Build Docker / Build Master (push) Successful in 21s
Build Docker / Build Bot (push) Failing after 19s
2023-08-24 17:38:29 +10:00
b0ab46562f actions: Syntax error fix
Some checks failed
Build Docker / Build Bot (push) Failing after 19s
Build Docker / Build Master (push) Failing after 21s
2023-08-24 17:36:16 +10:00
46096f0e84 actions: Fixed typo
Some checks failed
Build Docker / Build Master (push) Failing after 20s
Build Docker / Build Bot (push) Failing after 19s
2023-08-24 17:33:58 +10:00
166e223429 actions: Fixed tags
Some checks failed
Build Docker / Build Bot (push) Failing after 22s
Build Docker / Build Master (push) Failing after 23s
2023-08-24 17:31:40 +10:00
bc3f813b29 actions: Added dev build
All checks were successful
Build Docker / Build Master (push) Successful in 28s
Build Docker / Build Bot (push) Successful in 29s
2023-08-24 17:23:23 +10:00
aa11014ab9 actions: Start adding a dev build
All checks were successful
Build Docker / Build Master (push) Successful in 25s
Build Docker / Build Bot (push) Successful in 24s
2023-08-24 17:20:35 +10:00
fc8a0c3193 main: Cleaned up code 2023-08-24 17:18:24 +10:00
38526d5e08 Merge branch 'feature/stripe' into develop
All checks were successful
Build Docker / Build Bot (push) Successful in 24s
Build Docker / Build Master (push) Successful in 24s
2023-08-24 17:14:37 +10:00
2209e03158 main: Email test 3
All checks were successful
Build Docker / Build Bot (push) Successful in 21s
Build Docker / Build Master (push) Successful in 25s
2023-08-24 17:11:42 +10:00
cb849004b7 main: Added info to email
All checks were successful
Build Docker / Build Bot (push) Successful in 21s
Build Docker / Build Master (push) Successful in 25s
2023-08-24 17:05:01 +10:00
93333eed26 main: Cleaned up email
All checks were successful
Build Docker / Build Bot (push) Successful in 24s
Build Docker / Build Master (push) Successful in 24s
2023-08-24 16:57:05 +10:00
eb137b85d3 main: Added email test for stripe
All checks were successful
Build Docker / Build Bot (push) Successful in 24s
Build Docker / Build Master (push) Successful in 25s
2023-08-24 16:53:39 +10:00
969e5e17a5 main: Import stripe python module
All checks were successful
Build Docker / Build Master (push) Successful in 26s
Build Docker / Build Bot (push) Successful in 25s
2023-08-24 16:44:17 +10:00
230dc2a12a main: Added test stripe verification
All checks were successful
Build Docker / Build Bot (push) Successful in 20s
Build Docker / Build Master (push) Successful in 32s
2023-08-24 16:41:38 +10:00
d4fd470564 main: Stripe log all requests
All checks were successful
Build Docker / Build Master (push) Successful in 26s
Build Docker / Build Bot (push) Successful in 24s
2023-08-24 16:25:55 +10:00
5f56c1d0c2 main: Initial stripe test fix path
All checks were successful
Build Docker / Build Bot (push) Successful in 19s
Build Docker / Build Master (push) Successful in 25s
2023-08-24 16:17:27 +10:00
937620e86c main: Initial stripe test
All checks were successful
Build Docker / Build Bot (push) Successful in 22s
Build Docker / Build Master (push) Successful in 26s
2023-08-24 16:13:24 +10:00
36 changed files with 1548 additions and 88 deletions

View File

@@ -1,10 +1,16 @@
name: Build Docker
run-name: Build Docker Images
on: [push]
on:
push:
branches:
- '*'
- '*/*'
tags-ignore:
- '*'
jobs:
Build Master:
runs-on: ubuntu-latest
Build_Master_ARM:
runs-on: [ubuntu-latest, arm]
steps:
- name: Checkout
uses: actions/checkout@v2
@@ -21,15 +27,66 @@ jobs:
run : |
cd master
echo "${{ secrets.DOCKERGIT_TOKEN }}" | docker login git.woodburn.au -u nathanwoodburn --password-stdin
tag_num=$(git rev-parse --short HEAD)
echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}"
tag=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}
tag=${tag//\//-}
tag_num=${GITHUB_RUN_NUMBER}
echo "tag_num=$tag_num"
if [[ "$tag" == "main" ]]; then
tag="latest"
else
tag_num="${tag}-${tag_num}"
fi
docker build -t hnshosting-master:$tag_num .
docker tag hnshosting-master:$tag_num git.woodburn.au/nathanwoodburn/hnshosting-master:$tag_num-arm
docker push git.woodburn.au/nathanwoodburn/hnshosting-master:$tag_num-arm
docker tag hnshosting-master:$tag_num git.woodburn.au/nathanwoodburn/hnshosting-master:$tag-arm
docker push git.woodburn.au/nathanwoodburn/hnshosting-master:$tag-arm
Build_Master_AMD:
runs-on: [ubuntu-latest, amd]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Docker
run : |
apt-get install ca-certificates curl gnupg
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install docker-ce-cli -y
- name: Build Docker image
run : |
cd master
echo "${{ secrets.DOCKERGIT_TOKEN }}" | docker login git.woodburn.au -u nathanwoodburn --password-stdin
echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}"
tag=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}
tag=${tag//\//-}
tag_num=${GITHUB_RUN_NUMBER}
echo "tag_num=$tag_num"
if [[ "$tag" == "main" ]]; then
tag="latest"
else
tag_num="${tag}-${tag_num}"
fi
docker build -t hnshosting-master:$tag_num .
docker tag hnshosting-master:$tag_num git.woodburn.au/nathanwoodburn/hnshosting-master:$tag_num
docker push git.woodburn.au/nathanwoodburn/hnshosting-master:$tag_num
docker tag hnshosting-master:$tag_num git.woodburn.au/nathanwoodburn/hnshosting-master:latest
docker push git.woodburn.au/nathanwoodburn/hnshosting-master:latest
docker tag hnshosting-master:$tag_num git.woodburn.au/nathanwoodburn/hnshosting-master:$tag
docker push git.woodburn.au/nathanwoodburn/hnshosting-master:$tag
Build Bot:
runs-on: ubuntu-latest
Build_Bot_ARM:
runs-on: [ubuntu-latest, arm]
steps:
- name: Checkout
uses: actions/checkout@v2
@@ -46,9 +103,51 @@ jobs:
run : |
cd discord-bot
echo "${{ secrets.DOCKERGIT_TOKEN }}" | docker login git.woodburn.au -u nathanwoodburn --password-stdin
tag_num=$(git rev-parse --short HEAD)
echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}"
tag=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}
tag=${tag//\//-}
tag_num=${GITHUB_RUN_NUMBER}
if [[ "$tag" == "main" ]]; then
tag="latest"
else
tag_num="${tag}-${tag_num}"
fi
docker build -t hnshosting-bot:$tag_num .
docker tag hnshosting-bot:$tag_num git.woodburn.au/nathanwoodburn/hnshosting-bot:$tag_num-arm
docker push git.woodburn.au/nathanwoodburn/hnshosting-bot:$tag_num-arm
docker tag hnshosting-bot:$tag_num git.woodburn.au/nathanwoodburn/hnshosting-bot:$tag-arm
docker push git.woodburn.au/nathanwoodburn/hnshosting-bot:$tag-arm
Build_Bot_AMD:
runs-on: [ubuntu-latest, amd]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Docker
run : |
apt-get install ca-certificates curl gnupg
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install docker-ce-cli -y
- name: Build Docker image
run : |
cd discord-bot
echo "${{ secrets.DOCKERGIT_TOKEN }}" | docker login git.woodburn.au -u nathanwoodburn --password-stdin
echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}"
tag=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}
tag=${tag//\//-}
tag_num=${GITHUB_RUN_NUMBER}
if [[ "$tag" == "main" ]]; then
tag="latest"
else
tag_num="${tag}-${tag_num}"
fi
docker build -t hnshosting-bot:$tag_num .
docker tag hnshosting-bot:$tag_num git.woodburn.au/nathanwoodburn/hnshosting-bot:$tag_num
docker push git.woodburn.au/nathanwoodburn/hnshosting-bot:$tag_num
docker tag hnshosting-bot:$tag_num git.woodburn.au/nathanwoodburn/hnshosting-bot:latest
docker push git.woodburn.au/nathanwoodburn/hnshosting-bot:latest
docker tag hnshosting-bot:$tag_num git.woodburn.au/nathanwoodburn/hnshosting-bot:$tag
docker push git.woodburn.au/nathanwoodburn/hnshosting-bot:$tag

View File

@@ -0,0 +1,60 @@
name: Build Docker for Release
run-name: Build Docker Images
on:
push:
tags:
- '*'
jobs:
Build Master:
runs-on: [ubuntu-latest,arm]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Docker
run : |
apt-get install ca-certificates curl gnupg
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install docker-ce-cli -y
- name: Build Docker image
run : |
cd master
echo "${{ secrets.DOCKERGIT_TOKEN }}" | docker login git.woodburn.au -u nathanwoodburn --password-stdin
tag=${GITHUB_REF#refs/tags/}
docker build -t hnshosting-master:release-$tag .
docker tag hnshosting-master:release-$tag git.woodburn.au/nathanwoodburn/hnshosting-master:release-$tag
docker push git.woodburn.au/nathanwoodburn/hnshosting-master:release-$tag
docker tag hnshosting-master:release-$tag git.woodburn.au/nathanwoodburn/hnshosting-master:release
docker push git.woodburn.au/nathanwoodburn/hnshosting-master:release
Build Bot:
runs-on: [ubuntu-latest,arm]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Docker
run : |
apt-get install ca-certificates curl gnupg
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install docker-ce-cli -y
- name: Build Docker image
run : |
cd discord-bot
echo "${{ secrets.DOCKERGIT_TOKEN }}" | docker login git.woodburn.au -u nathanwoodburn --password-stdin
tag=${GITHUB_REF#refs/tags/}
docker build -t hnshosting-bot:release-$tag .
docker tag hnshosting-bot:release-$tag git.woodburn.au/nathanwoodburn/hnshosting-bot:release-$tag
docker push git.woodburn.au/nathanwoodburn/hnshosting-bot:release-$tag
docker tag hnshosting-bot:release-$tag git.woodburn.au/nathanwoodburn/hnshosting-bot:release
docker push git.woodburn.au/nathanwoodburn/hnshosting-bot:release

View File

@@ -11,12 +11,24 @@ The master server will be used to manage the worker servers.
The worker servers will be used to host the wordpress sites.
The bot will be used to provide an easier way to manage the master server.
![Overview of system](assets/overview.png)
| Legend | Description |
| --- | --- |
| Red Connections | Secured by VPN or over LAN ONLY. (NOT API SECURED) |
| Yellow Connections | HTTP/HTTPS public traffic |
## Features
- [x] Add new worker server to master server pool
- [x] Create wordpress site on random worker server
- [x] Optional Free mode (see Bot section)
## Usage
After installing the master and discord bot you can use the following commands (as bot owner).
```
/addworker <ip> <name> | add a worker to the master server pool (Make sure the master can access port 5000 on the worker, and don't allow anyone else to access it)
/addworker <ip> <private ip> <name> | add a worker to the master server pool
/listworkers | list all workers
/licence | Creates a licence key (valid for 1 wp site)
```
@@ -35,7 +47,7 @@ General commands (as anyone)
Docker is the easiest way to install the master server.
```sh
docker run -d -p 5000:5000 -e LICENCE-API=your-api-key -e WORKER_KEY=your-api-key --name hnshosting-master git.woodburn.au/nathanwoodburn/hnshosting-master:latest -v ./data:/data
docker run -d -p 5000:5000 -e LICENCE_KEY=your-api-key -e WORKER_KEY=your-api-key -e ADMIN_KEY=admin-key --name hnshosting-master git.woodburn.au/nathanwoodburn/hnshosting-master:latest -v ./data:/data
```
You can also mount a docker volume to /data to store the files instead of mounting a host directory.
@@ -50,6 +62,19 @@ Then to start the master api server
screen -dmS hnshosting-master python3 main.py
```
## Stripe webhook
Create a new webhook endpoint on stripe and set the url to https://master-server-domain:5000/stripe-webhook (note: you need to add a https proxy to your master server if you want to use stripe)
Add these environment variables to your master server
```yaml
STRIPE_SECRET: your-stripe-secret-key
STRIPE_ENDPOINT_SECRET: your-stripe-endpoint-secret
SMTP_HOST: smtp-server
SMTP_PORT: smtp-port
SMTP_USER: smtp-user
SMTP_PASS: smtp-pass
SMTP_FROM: smtp-from (eg. HNSHosting <hosting@nathan.woodburn.au>) This is optional
```
## Worker server install
@@ -61,15 +86,22 @@ cd hnshosting-wp/worker
chmod +x install.sh
./install.sh
```
Then to start the worker api server
Just press enter when it shows any prompts.
Start the worker api server using
```sh
screen -dmS hnshosting-worker python3 main.py
```
Add worker to master server:
Add worker to master server pool:
The master server will need to be able to access port 5000 on the worker server over the PRIVATE ip. This is not secured by the api key so make sure you don't allow anyone else to access it.
```sh
curl -X POST http://master-server-ip:5000/add-worker?worker=worker-name&ip=worker-server-ip -H "key: api-key"
curl -X POST http://master-server-ip:5000/add-worker?worker=worker-name&ip=worker-server-ip&priv=worker-server-private-ip -H "key: api-key"
```
Alternatively you can use the discord bot to add the worker to the master server pool.
```
/addworker <ip> <private ip> <name>
```
## Discord bot install
@@ -78,3 +110,20 @@ Docker install
```sh
docker run -d -e MASTER_IP=<MASTER SERVER IP> -e DISCORD_TOKEN=<YOUR-BOT-TOKEN> -e LICENCE_KEY=your-api-key -e WORKER_KEY=your-api-key --name hnshosting-bot git.woodburn.au/nathanwoodburn/hnshosting-bot:latest
```
Enable the free mode by setting the following environment variable.
This will allow you to create a wordpress site without using a licence key using the /createsite command.
```
FREE_MODE: true
```
## Hip2
HIP2 allows sending HNS to a domain.
To enable HIP2 on your wordpress site you should
1. Download the [HIP2 plugin](https://git.woodburn.au/nathanwoodburn/hnshosting-wp/raw/branch/main/assets/hns-wallet-plugin.zip)
2. Upload the plugin to your wordpress site
3. Activate the plugin
4. Go to the settings page and enter your HNS wallet address
5. Ensure it works by settings the permalink to post name and saving

Binary file not shown.

BIN
assets/overview.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

View File

@@ -3,6 +3,8 @@ from dotenv import load_dotenv
import discord
from discord import app_commands
import requests
import asyncio
import re
load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')
@@ -12,18 +14,23 @@ Master_Port = os.getenv('MASTER_PORT')
if Master_Port == None:
Master_Port = "5000"
FREE_LICENCE = os.getenv('FREE_LICENCE')
FREE_LICENCE = os.getenv('FREE_MODE')
if FREE_LICENCE == None:
FREE_LICENCE = False
else:
if FREE_LICENCE.lower() == "true":
FREE_LICENCE = True
else:
FREE_LICENCE = False
intents = discord.Intents.default()
client = discord.Client(intents=intents)
tree = app_commands.CommandTree(client)
@tree.command(name="addworker", description="Adds a worker to the master server")
async def addworker(ctx, ip: str, name: str):
async def addworker(ctx, ip: str,privateip: str, name: str):
if ctx.user.id == ADMINID:
r = requests.post(f"http://{Master_IP}:{Master_Port}/add-worker?worker={name}&ip={ip}",headers={"key":os.getenv('WORKER_KEY')})
r = requests.post(f"http://{Master_IP}:{Master_Port}/add-worker?worker={name}&ip={ip}&priv={privateip}",headers={"key":os.getenv('WORKER_KEY')})
if r.status_code == 200:
await ctx.response.send_message(f"Worker {name} added to the master server",ephemeral=True)
else:
@@ -45,11 +52,11 @@ async def listworkers(ctx):
await ctx.response.send_message(f"Error listing workers\n" + r.text,ephemeral=True)
else:
await ctx.response.send_message("You do not have permission to use this command",ephemeral=True)
update_bot_status()
@tree.command(name="licence", description="Gets a licence key")
async def license(ctx):
if ctx.user.id != ADMINID:
if FREE_LICENCE == False: # If free licences are enabled then anyone can get a licence
await ctx.response.send_message("You do not have permission to use this command",ephemeral=True)
return
@@ -64,16 +71,59 @@ async def license(ctx):
await ctx.response.send_message(f"Error getting license\n" + r.text,ephemeral=True)
@tree.command(name="createsite", description="Create a new WordPress site")
async def createsite(ctx, domain: str, licence: str):
async def createsite(ctx, domain: str, licence: str = None):
# Verify domain is valid
if domain == None:
await ctx.response.send_message("You must specify a domain",ephemeral=True)
return
if "http://" in domain or "https://" in domain:
await ctx.response.send_message("You must specify a domain without http:// or https://",ephemeral=True)
return
domain = domain.lower().strip()
# Regex for a domain (or a tld)
if not re.match(r'^[a-z0-9-]+(\.[a-z0-9-]+)*$', domain):
await ctx.response.send_message("You must specify a valid domain",ephemeral=True)
return
if FREE_LICENCE == True: # If free licences are enabled then auto generate a licence
r = requests.post(f"http://{Master_IP}:{Master_Port}/add-licence",headers={"key":os.getenv('LICENCE_KEY')})
if r.status_code == 200:
json = r.json()
if json['success'] == "true":
licence = json['licence_key']
else:
await ctx.response.send_message(f"Error getting license\n" + json['error'])
return
r = requests.post(f"http://{Master_IP}:{Master_Port}/new-site?domain={domain}",headers={"key":licence})
if r.status_code == 200:
json = r.json()
if json['success'] == "true":
await ctx.response.send_message(f"Site {domain} creating...\nPlease wait a few minutes and then send /siteinfo domain:{domain}")
await ctx.response.send_message(f"Site https://{domain} creating...\nI'll send you a message when it's ready")
ready = False
while ready == False:
ready = await check_site_ready(domain)
if ready == False:
await asyncio.sleep(5)
r = requests.get(f"http://{Master_IP}:{Master_Port}/site-info?domain={domain}")
json = r.json()
if json['success'] == "true":
if json['ip'] == '143.42.45.236':
await ctx.user.send(f"Site https://{domain} is ready!\nHere is the site info for {json['domain']}\nALIAS: `01.hnshosting.au`\nTLSA: `{json['tlsa']}`\nMake sure you put the TLSA in either `_443._tcp.{domain}` or `*.{domain}`")
else:
await ctx.user.send(f"Site https://{domain} is ready!\nHere is the site info for {json['domain']}\nA: `{json['ip']}`\nTLSA: `{json['tlsa']}`\nMake sure you put the TLSA in either `_443._tcp.{domain}` or `*.{domain}`")
else:
await ctx.user.send(f"Error getting site info\n" + json['error'])
else:
await ctx.response.send_message(f"Error creating site\n" + json['error'])
else:
await ctx.response.send_message(f"Error creating site\n" + r.text)
update_bot_status()
@tree.command(name="siteinfo", description="Get info about a WordPress site")
@@ -88,12 +138,37 @@ async def siteinfo(ctx, domain: str):
else:
await ctx.response.send_message(f"Error getting site info\n" + r.text)
async def check_site_ready(domain):
r = requests.get(f"http://{Master_IP}:{Master_Port}/site-info?domain={domain}")
if r.status_code == 200:
json = r.json()
if json['success'] == "true":
return True
else:
return False
else:
return False
def get_site_count():
r = requests.get(f"http://{Master_IP}:{Master_Port}/site-count")
if r.status_code == 200:
return r.text
else:
return "Error getting site count\n" + r.text
def update_bot_status():
site_count = get_site_count()
client.loop.create_task(client.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name="over " + site_count + " wordpress sites")))
# When the bot is ready
@client.event
async def on_ready():
global ADMINID
ADMINID = client.application.owner.id
await tree.sync()
await client.loop.create_task(client.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name="over HNSHosting wordpress")))
# Get the number of sites
site_count = get_site_count()
await client.loop.create_task(client.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name="over " + site_count + " wordpress sites")))
client.run(TOKEN)

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,19 +1,23 @@
from flask import Flask, request, jsonify
from flask import Flask, make_response, redirect, request, jsonify, render_template, send_from_directory
import dotenv
import os
import requests
import stripe # For stripe payments
import smtplib, ssl # For sending emails
dotenv.load_dotenv()
app = Flask(__name__)
logins = []
# API add license key (requires API key in header)
@app.route('/add-licence', methods=['POST'])
def add_license():
# Get API header
api_key = request.headers.get('key')
if api_key != os.getenv('LICENCE-API'):
if api_key != os.getenv('LICENCE_KEY'):
return jsonify({'error': 'Invalid API key', 'success': 'false'})
# Generate licence key
@@ -35,14 +39,22 @@ def new_site():
# Verify both API key and domain exist
if api_key == None:
return jsonify({'error': 'Missing API key', 'success': 'false'})
return jsonify({'error': 'No licence provided', 'success': 'false'})
if domain == None:
return jsonify({'error': 'Missing domain', 'success': 'false'})
# Check if API key is a valid site key
if api_key not in open('/data/licence_key.txt', 'r').read():
return jsonify({'error': 'Invalid API key', 'success': 'false'})
key_file = open('/data/licence_key.txt', 'r')
valid_key = False
for line in key_file.readlines():
if api_key == line.strip('\n'):
valid_key = True
break
key_file.close()
if not valid_key:
return jsonify({'error': 'Invalid licence', 'success': 'false'})
# Check if domain already exists
if site_exists(domain):
@@ -105,9 +117,10 @@ def new_site():
def add_worker():
worker=request.args.get('worker')
worker_IP=request.args.get('ip')
worker_PRIV=request.args.get('priv')
# Get API header
api_key = request.headers.get('key')
if api_key == None or worker == None or worker_IP == None:
if api_key == None or worker == None or worker_IP == None or worker_PRIV == None:
return jsonify({'error': 'Invalid API key or worker info', 'success': 'false'})
if api_key != os.getenv('WORKER_KEY'):
return jsonify({'error': 'Invalid API key', 'success': 'false'})
@@ -128,11 +141,11 @@ def add_worker():
# Add worker to file
workers_file = open('/data/workers.txt', 'a')
workers_file.write(worker + ":" + worker_IP + '\n')
workers_file.write(worker + ":" + worker_PRIV + ":"+ worker_IP + '\n')
workers_file.close()
online=True
resp=requests.get("http://"+worker_IP + ":5000/ping",timeout=2)
resp=requests.get("http://"+worker_PRIV + ":5000/ping",timeout=2)
if (resp.status_code != 200):
online=False
@@ -166,22 +179,34 @@ def list_workers():
for worker in workers:
# Check worker status
if not worker.__contains__(':'):
return jsonify({'error': 'No workers available', 'success': 'false'})
continue
online=True
try:
resp=requests.get("http://"+worker.split(':')[1].strip('\n') + ":5000/status",timeout=2)
if (resp.status_code != 200):
online=False
worker_list.append({'worker': worker.split(':')[0],'ip': worker.split(':')[1].strip('\n'), 'online': online, 'sites': 0, 'ready': 0})
worker_list.append({'worker': worker.split(':')[0],'ip': worker.split(':')[2].strip('\n'), 'online': online, 'sites': 0, 'status': 'offline'})
continue
sites = resp.json()['num_sites']
worker_list.append({'worker': worker.split(':')[0],'ip': worker.split(':')[1].strip('\n'), 'online': online, 'sites': sites, 'ready': 1})
availability = resp.json()['availability']
if availability == True:
worker_list.append({'worker': worker.split(':')[0],'ip': worker.split(':')[2].strip('\n'), 'online': online, 'sites': sites, 'status': 'ready'})
else:
worker_list.append({'worker': worker.split(':')[0],'ip': worker.split(':')[2].strip('\n'), 'online': online, 'sites': sites, 'status': 'full'})
except:
worker_list.append({'worker': worker.split(':')[0],'ip': worker.split(':')[2].strip('\n'), 'online': 'False', 'sites': 0, 'status': 'offline'})
continue
if len(worker_list) == 0:
return jsonify({'error': 'No workers available', 'success': 'false'})
return jsonify({'success': 'true', 'workers': worker_list})
@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'})
@@ -195,22 +220,23 @@ def site_status():
return jsonify({'error': 'Domain does not exist', 'success': 'false'})
# Get worker ip
ip = workerIP(worker)
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 jsonify({'success': 'true', 'domain': domain, 'ip': ip, 'tlsa': tlsa})
return jsonify({'success': 'true', 'domain': domain, 'ip': publicIP, 'tlsa': tlsa})
else:
return jsonify({'success': 'false', 'domain': domain, 'ip': ip, 'tlsa': 'none','error': 'No TLSA record found'})
return jsonify({'success': 'false', 'domain': domain, 'ip': publicIP, 'tlsa': 'none','error': 'No TLSA record found'})
@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'})
@@ -224,7 +250,7 @@ def tlsa():
return jsonify({'error': 'Domain does not exist', 'success': 'false'})
# Get worker ip
ip = workerIP(worker)
ip = workerIP_PRIV(worker)
# Get TLSA record
resp=requests.get("http://"+ip + ":5000/tlsa?domain=" + domain,timeout=2)
@@ -232,6 +258,67 @@ def tlsa():
return resp.json()
@app.route('/stripe', methods=['POST'])
def stripeapi():
payload = request.data
stripe.api_key = os.getenv('STRIPE_SECRET')
endpoint_secret = os.getenv('STRIPE_ENDPOINT_SECRET')
sig_header = request.headers.get('Stripe-Signature')
events = None
try:
event = stripe.Webhook.construct_event(
payload, sig_header, endpoint_secret
)
except ValueError as e:
# Invalid payload
return jsonify({'success': 'false'})
except stripe.error.SignatureVerificationError as e:
return jsonify({'success': 'false'})
if event.type == 'payment_intent.succeeded':
# Only for payments for licences
payment_intent = event.data.object
if payment_intent['amount'] != 1000:
return jsonify({'success': 'true'})
if payment_intent['description'] != "Subscription creation":
return jsonify({'success': 'true'})
# Get email
email = payment_intent['receipt_email']
# Create licence key
licence_key = os.urandom(16).hex()
# Add licence key to file
key_file = open('/data/licence_key.txt', 'a')
key_file.write(licence_key + '\n')
key_file.close()
# Send email
host = os.getenv('SMTP_HOST')
port = os.getenv('SMTP_PORT')
user = os.getenv('SMTP_USER')
password = os.getenv('SMTP_PASS')
from_email = os.getenv('SMTP_FROM')
if from_email == None:
from_email = "Hosting <"+user + ">"
context = ssl.create_default_context()
with smtplib.SMTP_SSL(host, port, context=context) as server:
server.login(user, password)
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 at https://hnshosting.au/register\n\n"\
+"Your licence key is: " + licence_key +"\nThanks,\nHNSHosting"
server.sendmail(from_email, email, message)
print('Licence sent via email for stripe payment', flush=True)
else:
print('Unhandled event type {}'.format(event.type))
return jsonify({'success': 'true'})
def get_sites_count():
# If file doesn't exist, create it
try:
@@ -281,7 +368,7 @@ def site_worker(domain):
sites_file.close()
return worker
def workerIP(worker):
def workerIP_PRIV(worker):
# If file doesn't exist, create it
try:
workers_file = open('/data/workers.txt', 'r')
@@ -299,6 +386,479 @@ def workerIP(worker):
workers_file.close()
return ip
def workerIP(worker):
# If file doesn't exist, create it
try:
workers_file = open('/data/workers.txt', 'r')
except FileNotFoundError:
workers_file = open('/data/workers.txt', 'w')
workers_file.close()
workers_file = open('/data/workers.txt', 'r')
ip = None
for line in workers_file.readlines():
if worker == line.split(':')[0]:
ip = line.split(':')[2].strip('\n')
break
workers_file.close()
return ip
# Home page
@app.route('/')
def home():
# Show index template
# Get site info
sites = []
try:
sites_file = open('/data/sites.txt', 'r')
sites = sites_file.readlines()
sites_file.close()
except FileNotFoundError:
pass
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:
worker_file = open('/data/workers.txt', 'r')
workers = worker_file.readlines()
worker_file.close()
except FileNotFoundError:
return render_template('register.html', buy_licence_link=buy_licence_link, ERROR_MESSAGE="No workers available\nPlease contact support")
# 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')
@app.route('/info')
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', title="Your site is installing.<br>Please wait...",message="")
if 'status' not in request.args:
# Get worker
worker = site_worker(domain)
if worker == None:
return render_template('success.html', title="Your site is installing.<br>Please wait...",message="Error: Domain does not exist<br>Please 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', title="Your site is ready!",message="Success<br>Domain: <code>" + domain + "</code><br>IP: <code>" + publicIP + "</code><br>TLSA: <code>" + tlsa + "</code><br>Make sure to add the TLSA record to <code>_443._tcp." + domain + "</code> or <code>*." + domain + "</code>")
else:
return render_template('success.html', title="Your site is installing.<br>Please wait...",message="Domain: <code>" + domain + "</code><br>IP: <code>" + publicIP + "</code><br>TLSA: Pending<br>No 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())
# Admin page
@app.route('/admin')
def admin():
# Check if logged in
login_key = request.cookies.get('login_key')
if login_key == None:
return "<h1>Admin</h1><br><form action='/login' method='POST'><input type='password' name='password'><input type='submit' value='Login'></form>"
if login_key not in logins:
return "<h1>Admin</h1><br><form action='/login' method='POST'><input type='password' name='password'><input type='submit' value='Login'></form>"
# Show some admin stuff
licences = []
try:
licences_file = open('/data/licence_key.txt', 'r')
licences = licences_file.readlines()
licences_file.close()
except FileNotFoundError:
pass
# Create html page
html = "<h1>Admin</h1><br>"
html += "<h2>Licences</h2>"
html += "<p>Number of licences: " + str(len(licences)) + "</p>"
html += "<p>Licences:</p>"
html += "<ul>"
for licence in licences:
html += "<li>" + licence.strip('\n') + "</li>"
html += "</ul>"
html += "<h2>API</h2>"
html += "<p>API key: " + os.getenv('LICENCE_KEY') + "</p>"
html += "<p>Worker key: " + os.getenv('WORKER_KEY') + "</p>"
html += "<h2>Stripe</h2>"
# Check if stripe is enabled
if os.getenv('STRIPE_SECRET') == None:
html += "<p>Stripe is not enabled</p>"
else:
html += "<p>Stripe is enabled</p>"
html += "<br><br><h2>Workers</h2>"
workers = []
try:
workers_file = open('/data/workers.txt', 'r')
workers = workers_file.readlines()
workers_file.close()
except FileNotFoundError:
pass
for worker in workers:
if not worker.__contains__(':'):
continue
html += "<p>Name: " + worker.split(':')[0] + " | Public IP " + worker.split(':')[2].strip('\n') + " | Private IP " + worker.split(':')[1]
# Check worker status
online=True
try:
resp=requests.get("http://"+worker.split(':')[1].strip('\n') + ":5000/status",timeout=2)
if (resp.status_code != 200):
html += " | Status: Offline"
else:
html += " | Status: Online | Sites: " + str(resp.json()['num_sites']) + " | Availability: " + str(resp.json()['availability'])
except:
html += " | Status: Offline"
html += "</p>"
html += "<h2>Sites</h2>"
sites = []
try:
sites_file = open('/data/sites.txt', 'r')
sites = sites_file.readlines()
sites_file.close()
except FileNotFoundError:
pass
for site in sites:
if not site.__contains__(':'):
continue
domain = site.split(':')[0]
html += "<p>Domain: <a href='https://"+ domain + "'>" + domain + "</a> | Worker: " + site.split(':')[1].strip('\n') + " | <a href='/info?domain=" + domain + "'>Info</a></p>"
html += "<br><br>"
# Form to add worker
html += "<h2>Add worker</h2>"
html += "<form action='/new-worker' method='POST'>"
html += "<p>Name: <input type='text' name='name'></p>"
html += "<p>Public IP: <input type='text' name='ip'></p>"
html += "<p>Private IP: <input type='text' name='priv'></p>"
html += "<input type='submit' value='Add worker'>"
html += "</form>"
html += "<br><h2><a href='/licence'>Add Licence</a></h2><br>"
# Form to add site
html += "<h2>Add site</h2>"
html += "<form action='/add-site' method='POST'>"
html += "<p>Domain: <input type='text' name='domain'></p>"
html += "<input type='submit' value='Add site'>"
html += "</form>"
html += "<br><a href='/logout'>Logout</a></h2>"
return html
@app.route('/add-site', methods=['POST'])
def addsite():
# Check for licence key
if 'licence' not in request.form:
# Check cookie
login_key = request.cookies.get('login_key')
if login_key == None:
return redirect('/admin')
if login_key not in logins:
return redirect('/admin')
else:
# Use licence key
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 jsonify({'error': 'Invalid licence', 'success': 'false'})
# 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()
# Get domain
domain = request.form['domain']
if domain == None:
return jsonify({'error': 'No domain sent', 'success': 'false'})
# Check if domain already exists
if site_exists(domain):
return jsonify({'error': 'Domain already exists', 'success': 'false'})
# Check if domain contains http:// or https://
if domain.startswith("http://") or domain.startswith("https://"):
return jsonify({'error': 'Domain should not contain http:// or https://', 'success': 'false'})
domain = domain.lower()
# Remove any trailing / or .
if domain.endswith('/'):
domain = domain.removesuffix('/')
if domain.endswith('.'):
domain = domain.removesuffix('.')
# Check if worker file exists
workers = None
try:
worker_file = open('/data/workers.txt', 'r')
workers = worker_file.readlines()
worker_file.close()
except FileNotFoundError:
return jsonify({'error': 'No workers available', 'success': 'false'})
# 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 jsonify({'error': 'No workers available', 'success': 'false'})
# 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)
html = "<h1>Site creating...</h1><br>"
html += "<p>Domain: " + domain + "</p>"
html += "<p>Worker: " + worker.split(':')[0] + "</p>"
html += "<p>Worker IP: " + worker.split(':')[1].strip('\n') + "</p>"
html += "<p><a href='/info?domain=" + domain + "'>Check status</a></p>"
return html
@app.route('/licence')
def licence():
# Check cookie
login_key = request.cookies.get('login_key')
if login_key == None:
return redirect('/admin')
if login_key not in logins:
return redirect('/admin')
licence_key = os.urandom(16).hex()
# Add license key to file
key_file = open('/data/licence_key.txt', 'a')
key_file.write(licence_key + '\n')
key_file.close()
return "<h1>Licence key</h1><br><p>" + licence_key + "</p><br><a href='/admin'>Back</a>"
@app.route('/new-worker', methods=['POST'])
def new_worker():
# Check cookie
login_key = request.cookies.get('login_key')
if login_key == None:
return redirect('/admin')
if login_key not in logins:
return redirect('/admin')
worker = request.form['name']
worker_IP = request.form['ip']
worker_PRIV = request.form['priv']
# Check worker file
try:
workers_file = open('/data/workers.txt', 'r')
except FileNotFoundError:
workers_file = open('/data/workers.txt', 'w')
workers_file.close()
workers_file = open('/data/workers.txt', 'r')
# Check if worker already exists
if worker in workers_file.read():
return jsonify({'error': 'Worker already exists', 'success': 'false'})
workers_file.close()
# Add worker to file
workers_file = open('/data/workers.txt', 'a')
workers_file.write(worker + ":" + worker_PRIV + ":"+ worker_IP + '\n')
workers_file.close()
return redirect('/admin')
@app.route('/logout')
def logout():
login_key = request.cookies.get('login_key')
if login_key == None:
return redirect('/admin')
if login_key not in logins:
return redirect('/admin')
logins.remove(login_key)
return redirect('/admin')
@app.route('/login', methods=['POST'])
def login():
# Handle login
print('Login attempt', flush=True)
# Check if form contains password
if 'password' not in request.form:
print('Login failed', flush=True)
return redirect('/failed-login')
password = request.form['password']
if os.getenv('ADMIN_KEY') == password:
print('Login success', flush=True)
# Generate login key
login_key = os.urandom(32).hex()
logins.append(login_key)
# Set cookie
resp = make_response(redirect('/admin'))
resp.set_cookie('login_key', login_key)
return resp
print('Login failed', flush=True)
return redirect('/failed-login')
@app.route('/failed-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)
@app.route('/terms')
def terms():
return render_template('terms.html')
# 404 route
@app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'), 404
# Start the server

View File

@@ -2,3 +2,4 @@ python-dotenv
requests
flask
jsonify
stripe

32
master/templates/404.html Normal file
View File

@@ -0,0 +1,32 @@
<!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>HNSHosting WP</title>
<link rel="canonical" href="https://wp.hnshosting.au/404.html">
<meta property="og:url" content="https://wp.hnshosting.au/404.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">
<link rel="stylesheet" href="assets/css/404.css">
<script async src="https://umami.woodburn.au/script.js" data-website-id="fc32daf3-6932-44ee-bbee-f853ce85d5f5"></script>
</head>
<body>
<p>HTTP:&nbsp;<span>404</span></p>
<div class="text-center">
<div class="text-start" style="display: inline-block;"><code><em>this_page</em>.<em>found</em>&nbsp;= false;</code><code><span>if</span>&nbsp;(<b>you_spelt_it_wrong</b>(<em>this_page</em>)) {<br><span class="tab-space"></span><b>try_again</b>();<br>}&nbsp;<span>else if</span> (!<em>this_page</em>.<b>content</b>) {<br><span class="tab-space"></span><b>you_spelt_it_wrong</b>('<i>You're lost! I'll send you back home</i>');<br><span class="tab-space"></span><span>window</span>.<b>location</b>&nbsp;= <em>home</em>;<br>}</code></div>
</div>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/404.js"></script>
<script src="assets/js/bold-and-dark.js"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,79 @@
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
background: #282828;
overflow-y: auto;
}
p {
font-family: "Bevan", cursive;
font-size: 130px;
margin: 10vh 0 0;
text-align: center;
overflow-y: auto;
letter-spacing: 5px;
/*background-color: black;*/
color: black;
text-shadow: 2px 2px 3px rgba(255, 255, 255, 0.1);
-webkit-background-clip: text;
-moz-background-clip: text;
background-clip: text;
}
p span {
font-size: 1.2em;
}
code {
color: #bdbdbd;
text-align: left;
display: block;
overflow-y: auto;
font-size: 16px;
margin: 0 30px 25px;
}
code span {
color: #f0c674;
}
code i {
color: #b5bd68;
}
code em {
color: #b294bb;
font-style: unset;
}
code b {
color: #81a2be;
font-weight: 500;
overflow-y: auto;
}
a {
color: #8abeb7;
font-family: monospace;
font-size: 20px;
text-decoration: underline;
overflow-y: auto;
margin-top: 10px;
display: inline-block;
}
@media screen and (max-width: 880px) {
p {
font-size: 14vw;
overflow-y: auto;
}
}
.tab-space {
margin-left: 2em;
}

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,30 @@
function callback(){
return function(){
alert("We're really sorry about that.");
window.location = '/';
}
}
var a = "world";
setTimeout(callback(), 7000);
function type(n, t) {
var str = document.getElementsByTagName("code")[n].innerHTML.toString();
var i = 0;
document.getElementsByTagName("code")[n].innerHTML = "";
setTimeout(function() {
var se = setInterval(function() {
i++;
document.getElementsByTagName("code")[n].innerHTML =
str.slice(0, i) + "|";
if (i == str.length) {
clearInterval(se);
document.getElementsByTagName("code")[n].innerHTML = str;
}
}, 10);
}, t);
}
type(0, 0);
type(1, 600);
type(2, 1300);

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);

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

@@ -0,0 +1,174 @@
<!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">
<script async src="https://umami.woodburn.au/script.js" data-website-id="fc32daf3-6932-44ee-bbee-f853ce85d5f5"></script>
</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">A simple and easy way to actually use your 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}} wordpress 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.56"></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-1z"></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-.5zm2.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-.5zm3.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-.5zM4 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-.5zM7.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-.5zm2.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-.5zM4.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-.5zm2.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-.5zM9 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-1zm3-3a1 1 0 0 0-1 1v1h2v-1a1 1 0 0 0-1-1"></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 servers has weekly 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 supported by OpenSystems</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.612m5.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.612"></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-2zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1zm13 2.383-4.708 2.825L15 11.105zm-.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-.741M1 11.105l4.708-2.897L1 5.383z"></path>
</svg></div>
<div class="px-2">
<h6 class="fw-bold mb-0">Email</h6>
<p class="text-muted mb-0"><a href="mailto:support@hnshosting.au">support@hnshosting.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><a href="/terms">Terms &amp; Privacy</a>
</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,71 @@
<!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">
<script async src="https://umami.woodburn.au/script.js" data-website-id="fc32daf3-6932-44ee-bbee-f853ce85d5f5"></script>
</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><br>Or thanks to the OpenSystems grant<br><a href="https://l.woodburn.au/discord" target="_blank">Register a free site here</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><a href="/terms">Terms &amp; Privacy</a>
</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,57 @@
<!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">
<script async src="https://umami.woodburn.au/script.js" data-website-id="fc32daf3-6932-44ee-bbee-f853ce85d5f5"></script>
</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">{{title | safe}}</h1></div><p class="text-center">{{message | safe}}</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><a href="/terms">Terms &amp; Privacy</a>
</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

@@ -0,0 +1,59 @@
<!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>Terms - HNSHosting</title>
<link rel="canonical" href="https://wp.hnshosting.au/terms.html">
<meta property="og:url" content="https://wp.hnshosting.au/terms.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">
<script async src="https://umami.woodburn.au/script.js" data-website-id="fc32daf3-6932-44ee-bbee-f853ce85d5f5"></script>
</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">Terms of Service</p>
</div>
</div>
<div class="row d-flex justify-content-center">
<div class="col">
<p>Terms of Service for HNSHosting Website Hosting<br><br>Last Updated: 17/11/23<br><br>Welcome to HNSHosting! Please carefully read the following terms before using our hosting services.<br><br>By using our website hosting services, you agree to comply with and be bound by the following terms and conditions. If you do not agree to these terms, please do not use our services.<br><br><strong>1. Acceptance of Terms:</strong><br>By accessing or using our website hosting services, you agree to these Terms of Service and all applicable laws and regulations.<br><br><strong>2. Hosting Services:</strong><br>HNSHosting provides hosting services for websites, and related content.<br><br><strong>3. Account Registration:</strong><br>To use our hosting services, you must create a Wordpress administrator account. You are responsible for maintaining the security of your account and any actions taken under your account credentials.<br><br><strong>4. Payment and Billing:</strong><br>Payment for hosting services is required in accordance with the pricing and billing terms specified on our website. Failure to pay may result in the suspension or termination of your hosting services.<br><br><strong>5. Content and Usage:</strong><br>You are solely responsible for the content hosted on your website. You agree not to host any content that violates applicable laws or infringes on the rights of others. This includes anything usually classified as <em>NSFW</em>. HNSHosting reserves the right to suspend or terminate services for any user found in violation of this provision.<br><br><strong>6. Data Security:</strong><br>We implement reasonable measures to protect the security of your data, but we cannot guarantee its absolute security. You should backup any critical data using your own backup solution.<br><br><strong>7. Uptime and Downtime:</strong><br>HNSHosting strives to provide high uptime for its hosting services. However, downtime may occur for maintenance or other reasons. We will make reasonable efforts to notify you in advance of scheduled maintenance.<br><br><strong>8. Support:</strong><br>We offer customer support for technical issues related to our hosting services. Support availability and response times may vary. We can not guarantee support for issues unrelated to our hosting services.<br><br><strong>9. Termination:</strong><br>HNSHosting reserves the right to terminate or suspend your account at any time for violation of these terms or for any other reason. You may also terminate your account by contacting us.<br><br><strong>10. Changes to Terms:</strong><br>HNSHosting reserves the right to modify these Terms of Service at any time. Any changes will be effective immediately upon posting on our website. It is your responsibility to review these terms regularly.<br><br><br>By using our hosting services, you agree to these terms. If you have any questions or concerns, please contact us.<br>Thank you for choosing HNSHosting Services!<br><br><br><br><br><br></p>
</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><a href="/terms">Terms &amp; Privacy</a>
</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

@@ -2,23 +2,44 @@
# Initial install for all prerequisites for the project.
# This makes it quicker to get each site up and running.
# Update the system
sudo apt update && sudo apt upgrade -y
# Stop kernel prompts
export DEBIAN_FRONTEND=noninteractive
export NEEDRESTART_MODE=a
echo "Dpkg::Options { \"--force-confdef\"; \"--force-confold\"; };" | sudo tee /etc/apt/apt.conf.d/local
KERNEL_VERSION=$(uname -r)
sudo apt-mark hold linux-image-generic linux-headers-generic linux-generic linux-image-$KERNEL_VERSION linux-headers-$KERNEL_VERSION
# Install Docker
sudo apt install apt-transport-https ca-certificates curl software-properties-common -y
sudo apt update
sudo apt install apt-transport-https ca-certificates curl software-properties-common python3-pip nginx -y
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
apt-cache policy docker-ce
sudo apt install docker-ce -y
sudo apt install docker-compose -y
# Install NGINX
sudo apt install nginx -y
sudo apt install docker-ce docker-compose -y
# Install python prerequisites
sudo apt install python3-pip -y
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 &
wait

View File

@@ -26,7 +26,7 @@ def new_site():
sites_file.close()
# New site in background
thread = threading.Thread(target=new_site, args=(domain, 5000 + count))
thread = threading.Thread(target=new_site_script, args=(domain,))
thread.start()
@@ -44,8 +44,8 @@ def tlsa():
tlsa_file = open('wordpress-'+domain+'/tlsa.txt', 'r')
tlsa = tlsa_file.readlines()
tlsa_file.close()
except FileNotFoundError:
return jsonify({'error': 'TLSA record not found', 'success': 'false'})
except FileNotFoundError as e:
return jsonify({'error': 'TLSA record not found', 'success': 'false', 'ex': str(e)})
# Remove newlines
tlsa = tlsa[0].strip('\n')
@@ -67,16 +67,11 @@ def ping():
return 'pong'
def get_sites_count():
# If file doesn't exist, create it
try:
sites_file = open('sites.txt', 'r')
except FileNotFoundError:
sites_file = open('sites.txt', 'w')
sites_file.close()
sites_file = open('sites.txt', 'r')
print(sites_file.readlines())
# Get number of files in nginx/sites
dir = os.listdir('/etc/nginx/sites-available')
num_Sites = len(dir) - 1
# Return number of lines in file
return len(sites_file.readlines())
return num_Sites
def site_exists(domain):
# If file doesn't exist, create it
@@ -93,8 +88,8 @@ def site_exists(domain):
else:
return False
def new_site(domain,port):
script = 'bash wp.sh ' + domain + ' '+ str(port)
def new_site_script(domain):
script = 'bash wp.sh ' + domain
os.system(script)
# Start the server

View File

@@ -4,10 +4,8 @@
# Then it will create an NGINX reverse proxy to the container.
# USAGE:
# ./wp.sh [domain] [port offset]
# ./wp.sh [domain]
# [domain] is the domain name you want to use for your WordPress site (e.g. docker.freeconcept)
# [port offset] is the offset you want to use for the port numbers.
# This is used if you want to run multiple instances of WordPress on the same server. (e.g. 0, 1, 2, 3, etc.)
# Variables
# Set the domain name
@@ -21,15 +19,6 @@ fi
DOMAIN="$1"
echo "Setting up on domain name: $DOMAIN"
# Set port offset
# This is used to offset the port numbers so you can run multiple instances of WordPress on the same server.
if [ -z "$2" ]
then
PORT_OFFSET=0
else
PORT_OFFSET="$2"
fi
mkdir wordpress-$DOMAIN
cd wordpress-$DOMAIN
@@ -38,6 +27,8 @@ MYSQL_ROOT_PASSWORD=$(openssl rand -base64 32)
MYSQL_PASSWORD=$(openssl rand -base64 32)
# Create port numbers
# Offset is the number of files in nginx/sites-enabled
PORT_OFFSET=$(ls -1 /etc/nginx/sites-enabled | wc -l)
WORDPRESS_PORT=$((8000 + $PORT_OFFSET))
# Create the docker config file
@@ -52,6 +43,8 @@ services:
MYSQL_DATABASE: WordPressDatabase
MYSQL_USER: WordPressUser
MYSQL_PASSWORD: $MYSQL_PASSWORD
volumes:
- mysql:/var/lib/mysql
wordpress:
depends_on:
- ${DOMAIN}db
@@ -65,9 +58,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
@@ -82,14 +77,24 @@ printf "server {
server_name $DOMAIN *.$DOMAIN;
proxy_ssl_server_name on;
location / {
proxy_set_header Accept-Encoding \"\";
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header Host \$http_host;
proxy_set_header X-Forwarded-Host \$http_host;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_pass $URL;
sub_filter '</body>' '<script src=\"https://nathan.woodburn/https.js\"></script></body>';
sub_filter_once on;
}
location = /.well-known/wallets/HNS {
proxy_pass $URL;
proxy_set_header Host \$http_host;
rewrite ^(.*)$ \$1/ break;
}
listen 443 ssl;
ssl_certificate /etc/ssl/$DOMAIN.crt;