Compare commits

...

60 Commits

Author SHA1 Message Date
3wc cfb323bf60 Merge branch 'yc-templates' into yolocolo
continuous-integration/drone/push Build is passing Details
2021-07-22 01:03:02 +02:00
3wc 8c7197f118 Merge branch 'docker' into yolocolo 2021-07-22 01:02:34 +02:00
3wc fb83f52162 Merge branch 'master' into yolocolo 2021-07-22 00:57:01 +02:00
3wc 982556a2c5 Tag with current branch, instead of `latest`
continuous-integration/drone/pr Build was killed Details
continuous-integration/drone/push Build is passing Details
2021-07-22 00:28:33 +02:00
3wc 13646e64da Make docker-compose file less demanding
continuous-integration/drone/pr Build is failing Details
continuous-integration/drone/push Build is passing Details
2021-07-21 23:50:47 +02:00
3wc 67149f437a Changes from @decentral1se code review 2021-07-21 23:50:47 +02:00
3wc 308ac05fe6 Add openssh-cient to Dockerfile for ssh-keyscan 2021-07-21 23:50:47 +02:00
3wc c378c2b287 STRIPE_SECRET_KEY not STRIPE_PUBLISHABLE_KEY 2021-07-21 23:50:47 +02:00
3wc 5367822747 Load secrets from files if _FILE vars are set 2021-07-21 23:50:47 +02:00
3wc e295b4420c Docker updates for libvirtd 2021-07-21 23:50:47 +02:00
3wc e4180b8306 Use Flask server in development 2021-07-21 23:50:47 +02:00
3wc 5cd5126039 Multi-stage build oh my! 2021-07-21 23:50:47 +02:00
3wc f8e9ab2482 Initial attempt at Docker 2021-07-21 23:50:47 +02:00
3wc 487a1ac0a3 Revert accidental change to main images 2021-07-21 23:30:14 +02:00
3wc 71344fbf4d Merge branch 'yc-templates' into yolocolo 2021-07-21 22:49:17 +02:00
3wc 6f3ecf991d Custom theme fixes 2021-07-21 22:48:54 +02:00
3wc 40aa3bccd3 Load YOLOCOLO templates from a "theme" folder..
..configurable using the THEME env var.

Defaults to normal Capsul theme.
2021-07-21 22:24:25 +02:00
3wc bcc3f20b27 Tweak table style 2021-07-21 22:12:13 +02:00
3wc 8bd3971545 Improve form styling 2021-07-21 22:12:13 +02:00
3wc c639899cd0 Remove cash payment option 2021-07-21 22:12:13 +02:00
3wc a47c430855 Further colour tweak 2021-07-21 22:12:13 +02:00
3wc d5362897df Fix typo, tweak colours 2021-07-21 22:12:13 +02:00
3wc a52d183f2e More cheeky template changes 2021-07-21 22:12:13 +02:00
3wc 73042d1705 Disco updates for YOLOCOLO site 2021-07-21 22:12:13 +02:00
3wc d3078fc5ce Merge branch 'yc-templates' into yolocolo 2021-07-21 21:07:59 +02:00
3wc d60238f6f0 Improve form styling 2021-07-21 21:07:51 +02:00
3wc ab55146d41 Remove cash payment option 2021-07-21 21:07:49 +02:00
3wc 7191213646 Further colour tweak 2021-07-21 21:07:27 +02:00
3wc 8c802a977a Fix typo, tweak colours 2021-07-21 21:07:27 +02:00
3wc 929aa29663 More cheeky template changes 2021-07-21 21:07:26 +02:00
3wc 61beee8d3b Disco updates for YOLOCOLO site 2021-07-21 21:07:03 +02:00
3wc 8586b85095 Merge branch 'master' into yolocolo
continuous-integration/drone/push Build is failing Details
2021-07-21 20:38:36 +02:00
3wc b2b78e0015 Merge branch 'yc-templates' into yolocolo
continuous-integration/drone/push Build is passing Details
2021-07-21 11:43:17 +02:00
3wc d6f4be8197 Improve form styling 2021-07-21 11:43:04 +02:00
3wc 5d3d0a1c5e Merge branch 'docker' into yolocolo 2021-07-21 11:38:58 +02:00
3wc fc7e264178 Make docker-compose file less demanding
continuous-integration/drone/pr Build was killed Details
continuous-integration/drone/push Build is passing Details
2021-07-21 11:38:01 +02:00
3wc 157e81e6e5 Merge branch 'yc-templates' into yolocolo
continuous-integration/drone/push Build is passing Details
2021-07-21 02:02:58 +02:00
3wc 97f9486ea3 Remove cash payment option 2021-07-21 02:02:21 +02:00
3wc 4b90a6c7ae Merge branch 'yc-templates' into yolocolo
continuous-integration/drone/push Build is passing Details
2021-07-21 01:56:45 +02:00
3wc adc3342a8c Further colour tweak 2021-07-21 01:56:36 +02:00
3wc f8bbdcc3c5 Merge branch 'yc-templates' into yolocolo
continuous-integration/drone/push Build was killed Details
2021-07-21 01:54:35 +02:00
3wc 1133caa8a4 Fix typo, tweak colours 2021-07-21 01:54:21 +02:00
3wc 1f384f34b5 Merge branch 'yc-templates' into yolocolo
continuous-integration/drone/push Build was killed Details
2021-07-21 01:44:52 +02:00
3wc c25d85bbdd More cheeky template changes 2021-07-21 01:44:45 +02:00
3wc 0f4ac8e444 Merge branch 'yc-templates' into yolocolo
continuous-integration/drone/push Build is passing Details
2021-07-21 01:15:51 +02:00
3wc 3cf501a393 Disco updates for YOLOCOLO site 2021-07-21 01:13:52 +02:00
3wc 180efa01af Merge branch 'optional-btcpay' into yolocolo
continuous-integration/drone/push Build is passing Details
2021-07-21 00:30:34 +02:00
3wc f5c079ffc2 Un-hard-code SSH key name
continuous-integration/drone/push Build is passing Details
2021-07-20 23:55:03 +02:00
3wc 0e5dfe6bde Last re-hard-coding for "working" joy 2021-07-20 23:55:03 +02:00
3wc 2adbb8d94c Further filthy fix for local libvirt 2021-07-20 23:55:03 +02:00
3wc 8446d11720 Revert hardcoded local path to tank dir 2021-07-20 23:55:03 +02:00
3wc a580b04659 Bag of hacks to get local libvirt working 2021-07-20 23:55:03 +02:00
3wc 2e6894ad14 Changes from @decentral1se code review
continuous-integration/drone/pr Build is failing Details
continuous-integration/drone/push Build is passing Details
2021-07-20 23:48:23 +02:00
3wc 2e6c6517f3 Add openssh-cient to Dockerfile for ssh-keyscan
continuous-integration/drone/pr Build encountered an error Details
continuous-integration/drone/push Build is passing Details
2021-07-20 01:52:17 +02:00
3wc be6c1b38b7 STRIPE_SECRET_KEY not STRIPE_PUBLISHABLE_KEY
continuous-integration/drone/push Build is failing Details
continuous-integration/drone/pr Build is failing Details
2021-07-19 01:17:18 +02:00
3wc aa8e129913 Load secrets from files if _FILE vars are set 2021-07-19 00:24:22 +02:00
3wc 71e09807a7 Docker updates for libvirtd 2021-07-15 00:13:11 +02:00
3wc 4816170c03 Use Flask server in development 2021-07-15 00:13:11 +02:00
3wc 6af241e8be Multi-stage build oh my! 2021-07-15 00:13:11 +02:00
3wc c8ec53f207 Initial attempt at Docker 2021-07-15 00:13:11 +02:00
25 changed files with 580 additions and 167 deletions

13
.drone.yml Normal file
View File

@ -0,0 +1,13 @@
---
kind: pipeline
name: publish docker image
steps:
- name: build and publish
image: plugins/docker
settings:
username:
from_secret: docker_reg_username_3wc
password:
from_secret: docker_reg_passwd_3wc
repo: 3wordchant/capsul-flask
tags: ${DRONE_COMMIT_BRANCH}

48
Dockerfile Normal file
View File

@ -0,0 +1,48 @@
FROM python:3.8-alpine as build
RUN apk add --no-cache \
build-base \
gcc \
gettext \
git \
jpeg-dev \
libffi-dev \
libjpeg \
musl-dev \
postgresql-dev \
python3-dev \
zlib-dev
RUN mkdir -p /app/{code,venv}
WORKDIR /app/code
COPY Pipfile Pipfile.lock /app/code/
RUN python3 -m venv /app/venv
RUN pip install pipenv setuptools
ENV PATH="/app/venv/bin:$PATH" VIRTUAL_ENV="/app/venv"
RUN pip install wheel cppy
# Install dependencies into the virtual environment with Pipenv
RUN pipenv install --deploy --verbose
FROM python:3.8-alpine
RUN apk add --no-cache \
cloud-utils \
libjpeg \
libpq \
libstdc++ \
libvirt-client \
openssh-client \
virt-install
COPY . /app/code/
WORKDIR /app/code
COPY --from=build /app/venv /app/venv
ENV PATH="/app/venv/bin:$PATH" VIRTUAL_ENV="/app/venv"
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "-k", "gevent", "--worker-connections", "1000", "app:app"]
VOLUME /app/code
EXPOSE 5000

View File

@ -2,6 +2,7 @@ import logging
from logging.config import dictConfig as logging_dict_config
import atexit
import jinja2
import os
import hashlib
import requests
@ -26,8 +27,24 @@ class StdoutMockFlaskMail:
def send(self, message: Message):
current_app.logger.info(f"Email would have been sent if configured:\n\nto: {','.join(message.recipients)}\nsubject: {message.subject}\nbody:\n\n{message.body}\n\n")
load_dotenv(find_dotenv())
for var_name in [
"SPOKE_HOST_TOKEN", "HUB_TOKEN", "STRIPE_SECRET_KEY",
"BTCPAY_PRIVATE_KEY", "MAIL_PASSWORD"
]:
var = os.environ.get(f"{var_name}_FILE")
if not var:
continue
if not os.path.isfile(var):
continue
with open(var) as secret_file:
os.environ[var_name] = secret_file.read().rstrip('\n')
del os.environ[f"{var_name}_FILE"]
app = Flask(__name__)
app.config.from_mapping(
@ -71,7 +88,9 @@ app.config.from_mapping(
#STRIPE_WEBHOOK_SECRET=os.environ.get("STRIPE_WEBHOOK_SECRET", default="")
BTCPAY_PRIVATE_KEY=os.environ.get("BTCPAY_PRIVATE_KEY", default="").replace("\\n", "\n"),
BTCPAY_URL=os.environ.get("BTCPAY_URL", default="")
BTCPAY_URL=os.environ.get("BTCPAY_URL", default=""),
THEME=os.environ.get("THEME", default="")
)
app.config['HUB_URL'] = os.environ.get("HUB_URL", default=app.config['BASE_URL'])
@ -154,6 +173,14 @@ is_running_server = ('flask run' in command_line) or ('gunicorn' in command_line
app.logger.info(f"is_running_server: {is_running_server}")
if app.config['THEME'] != "":
my_loader = jinja2.ChoiceLoader([
jinja2.FileSystemLoader(
[os.path.join('capsulflask', 'theme', app.config['THEME']),
'capsulflask/templates']),
])
app.jinja_loader = my_loader
if app.config['HUB_MODE_ENABLED']:
if app.config['HUB_MODEL'] == "capsul-flask":

View File

@ -178,4 +178,4 @@ def on_create_claimed(payload, host_id):
network_name=payload['network_name'],
public_ipv4=payload['public_ipv4'],
ssh_authorized_keys=list(map(lambda x: x["name"], payload['ssh_authorized_keys'])),
)
)

View File

@ -227,12 +227,13 @@ class CapsulFlaskHub(VirtualizationInterface):
except:
# no need to do anything here since if it cant be parsed then generic_operation will handle it.
pass
if error_message != "":
raise ValueError(f"create capsul operation {operation_id} on {assigned_hosts} failed with {error_message}")
if number_of_assigned != 1:
assigned_hosts_string = ", ".join(assigned_hosts)
raise ValueError(f"expected create capsul operation {operation_id} to be assigned to one host, it was assigned to {number_of_assigned} ({assigned_hosts_string})")
if error_message != "":
raise ValueError(f"create capsul operation {operation_id} on {assigned_hosts_string} failed with {error_message}")
def destroy(self, email: str, id: str):

View File

@ -3,7 +3,7 @@
# check available RAM and IPv4s
ram_bytes_to_allocate="$1"
ram_bytes_available=$(grep -E "^(size|memory_available_bytes)" /proc/spl/kstat/zfs/arcstats | awk '{sum+=$3} END {printf "%.0f", sum}')
ram_bytes_available="$(($(grep Available /proc/meminfo | grep -o '[0-9]*') * 1024))"
ram_bytes_remainder="$((ram_bytes_available - ram_bytes_to_allocate))"
if echo "$ram_bytes_to_allocate" | grep -vqE "^[0-9]+$"; then
@ -11,8 +11,8 @@ if echo "$ram_bytes_to_allocate" | grep -vqE "^[0-9]+$"; then
exit 1
fi
# 20GB
if [ "$ram_bytes_remainder" -le $((20 * 1024 * 1024 * 1024)) ]; then
# 0.25GB
if [ "$ram_bytes_remainder" -le $((1 * 1024 * 1024 * 1024 / 4)) ]; then
echo "VM is requesting more RAM than $(hostname -f) has available."
echo "Bytes requested: $ram_bytes_to_allocate"
echo "Bytes available: $ram_bytes_available"

View File

@ -6,6 +6,7 @@
vmname="$1"
template_file="/tank/img/$2"
qemu_tank_dir="/tank"
vcpus="$3"
memory="$4"
pubkeys="$5"
@ -50,40 +51,40 @@ if echo "$public_ipv4" | grep -vqE "^[0-9.]+$"; then
exit 1
fi
disk="/tank/vm/$vmname.qcow2"
cdrom="/tank/vm/$vmname.iso"
xml="/tank/vm/$vmname.xml"
disk="$vmname.qcow2"
cdrom="$vmname.iso"
xml="$vmname.xml"
if [ -f /tank/vm/$vmname.qcow2 ]; then
echo "Randomly generated name matched an existing VM! Odds are like one in a billion. Buy a lotto ticket."
exit 1
fi
cp "$template_file" "$disk"
cp "$template_file" "/tank/vm/$disk"
cp /tank/config/cyberia-cloudinit.yml /tmp/cloudinit.yml
echo "$pubkeys" | while IFS= read -r line; do
echo " - $line" >> /tmp/cloudinit.yml
done
cloud-localds "$cdrom" /tmp/cloudinit.yml
cloud-localds "/tank/vm/$cdrom" /tmp/cloudinit.yml
qemu-img resize "$disk" "$root_volume_size"
qemu-img resize "/tank/vm/$disk" "$root_volume_size"
virt-install \
--memory "$memory" \
--vcpus "$vcpus" \
--name "$vmname" \
--disk "$disk",bus=virtio \
--disk "$cdrom",device=cdrom \
--disk "$qemu_tank_dir/vm/$disk",bus=virtio \
--disk "$qemu_tank_dir/vm/$cdrom",device=cdrom \
--os-type Linux \
--os-variant generic \
--virt-type kvm \
--graphics vnc,listen=127.0.0.1 \
--network network=$network_name,filterref=clean-traffic,model=virtio \
--network network=$network_name,model=virtio \
--import \
--print-xml > "$xml"
--print-xml > "/tank/vm/$xml"
chmod 0600 "$xml" "$disk" "$cdrom"
virsh define "$xml"
chmod 0600 "/tank/vm/$xml" "/tank/vm/$disk" "/tank/vm/$cdrom"
virsh define "/tank/vm/$xml"
virsh start "$vmname"
echo "success"

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -1,8 +1,8 @@
html {
color: #bdc7b8;
color: #241e1e;
font: calc(0.40rem + 1vmin) monospace;
overflow-y: scroll;
background-color: #241e1e;
background-color: #bdc7b8;
}
body {
@ -19,8 +19,8 @@ body {
}
a {
color:#6CF;
text-shadow: 1px 1px 0px #000c;
color:#00517a;
text-shadow: 1px 1px 0px #eee;
}
a.no-shadow {
@ -28,7 +28,7 @@ a.no-shadow {
}
a:hover, a:active, a:visited {
color: #b5bd68;
color: #323417;
}
.nav-links a {
@ -59,11 +59,11 @@ h1, h2, h3, h4, h5 {
margin: initial;
padding: initial;
text-transform: uppercase;
text-shadow: 2px 2px 0px #0007;
text-shadow: 2px 2px 0px #eee;
}
main {
border: 1px dashed #bdc7b8;
border: 1px dashed #241e1e;
padding: 1rem;
margin-bottom: 2em;
@ -143,7 +143,7 @@ input, textarea, select, label {
input, select, textarea {
outline: 0;
padding: 0.25em 0.5em;
color: #bdc7b8;
color: #241e1e;
background-color: #bdc7b805;
}

View File

@ -0,0 +1,35 @@
html {
color: #241e1e !important;
background-color: #bdc7b8 !important;
}
a {
color:#00517a !important;
text-shadow: 1px 1px 0px #eee !important;
}
a:hover, a:active, a:visited {
color: #323417 !important;
}
.nav-links a {
text-shadow: 2px 2px 0px #eee !important;
}
h1, h2, h3, h4, h5 {
text-shadow: 2px 2px 0px #eee;
}
main {
border: 1px dashed #241e1e !important;
}
input, select, textarea {
color: #241e1e !important;
}
th {
border-right: 1px solid #eee !important;
text-align: left !important;
}

View File

@ -49,8 +49,6 @@
{% if btcpay_enabled %}
<li><a href="/payment/btcpay">Add funds with Bitcoin/Litecoin/Monero (btcpay)</a></li>
{% endif %}
<li>Cash: email <a href="mailto:treasurer@cyberia.club">treasurer@cyberia.club</a></li>
</ul>
</li>
</ul>

View File

@ -13,7 +13,7 @@
<nav>
<div class="row justify-space-between half-margin">
<div>
<a href="/"><b>Capsul</b></a>💊
🦉 <a href="/"><b>YOLOCOLO</b></a>
</div>
<div>
&nbsp;
@ -27,7 +27,6 @@
<div class="row justify-center half-margin wrap nav-links">
<a href="/pricing">Pricing</a>
<a href="/faq">FAQ</a>
<a href="/changelog">Changelog</a>
{% if session["account"] %}
<a href="/console">Capsuls</a>
@ -47,11 +46,12 @@
</main>
{% block subcontent %}{% endblock %}
<footer>
(c) Attribution-ShareAlike 4.0 International <br/>
&nbsp;&nbsp;&nbsp;&nbsp;A service by Cyberia Computer Club 2020-<span class="bigtext"></span> <br/>
<br/>
<br/>
<a href="https://giit.cyberia.club/~forest/capsul-flask/tree/master/capsulflask{% block pagesource %}{% endblock %}">View page source</a>
This server runs <a
href="https://giit.cyberia.club/~forest/capsul-flask">capsul-flask</a> by
Cyberia Computer Club, available under the <a
href="https://creativecommons.org/licenses/by-sa/4.0/">Attribution-ShareAlike
4.0 International</a> licence.<br/><br/>
<a href="https://git.autonomic.zone/3wordchant/capsul-flask/src/branch/yolocolo/capsulflask{% block pagesource %}{% endblock %}">View page source</a>
</footer>
</body>
</html>

View File

@ -10,82 +10,32 @@
<p>
<ul>
<li>
Which instance type should I buy?
<p>There are no hard rules for this sort of thing, but here are some guidelines:</p>
<p>f1-xs: blog, vpn, bot, cgit</p>
<p>f1-s: a bot, owncloud, gitea, popular blog</p>
<p>f1-m: docker host, build system</p>
<p>f1-l: large webservice, rotund java app</p>
<p>f1-x: gitlab (wow such memory very devops</p>
<p>f1-xx: something gargantuan</p>
What is this?
<p>
This is a <strong>technical demo</strong> of <a
href="https://giit.cyberia.club/~forest/capsul-flask">Capsul</a>, for the
as-yet-untitled <a href="https://coops.tech">Cotech</a> server hosting
initiative, which you can <a
href="https://community.coops.tech/t/call-for-input-v2-co-op-vps-survey/2802/9">read
about on the Cotech forum</a>.
</p>
</li>
<li>
How do I log in?
<p>ssh to the ip provided to you using the cyberian user.</p>
<pre class='code'>$ ssh cyberian@1.2.3.4</pre>
<p>For more information, see <a href="/about-ssh">Understanding the Secure Shell Protocol (SSH)</a>.</p>
What do you mean, "technical demo"?
<p>No backups</p>
<p>No service level agreement</p>
<p>"Best effort" support</p>
</li>
<li>
How do I change to the root user?
<p>The cyberian user has passwordless sudo access by default. This should work:</p>
<pre class='code'>
# Linux
$ sudo su -
# OpenBSD
$ doas su -</pre>
Where can I get this, but, more reliable?
<p>Cyberia, the authors of this platform, run the canonical instance, <a
href="https://capsul.org">Capsul.org</a>, on hardware they own. Please
send them your money! (cash, crypto, or card accepted).</p>
</li>
<li>
Do you offer reverse DNS?
<p>We do, but right now it's a manual process. Shoot us an email and we'll get it done.</p>
</li>
<li>
What if I don't pay / don't maintain my payments?
<p>Your VM will eventually be deleted.
Capsul will send you a few inoffensive reminders as that termination date approaches.
</p>
</li>
<li>
Besides my virtual machines and payments, what information do you keep about me?
<p>We associate an email address with every VM so that we can track payment and respond to support requests.</p>
<p>If you pay with a credit card, Stripe stores some additional details about you that we literally cannot delete.</p>
</li>
<li>
What can I do with my VM?
<p>Make it into a mailserver, a tor relay, a VPN host, whatever you'd like - we do have one small request, though.</p>
<p>Crypto mining on capsul is currently considered obnoxious behavior, because the hashrates on our CPUs is so low and because mining crypto consumes entire processor cores that could have otherwise been shared between many dozens of other users.</p>
<p>In the future, if we have plentiful CPU resources, we may come out with a tier more suitable for mining - maybe a high cpu tier or similar, where each VM gets a full dedicated core and sharing them is not anticipated.</p>
<p>We will never snoop on your traffic or inspect what's going on inside of our customer virtual machines - we don't want to. We hope that you'll extend us a similar courtesy and try not to use too much of our shared CPU resources. Capsul is currently a shared (resource-wise) world, and we all must live in it together!</p>
<p>Also, mandatory: our systems exist within the USA, and as such those systems are bound by US law.</p>
</li>
<li>
Can you recover my passwords/insert new keys?
<p>Can we? Technically yes. Will we? No, never. It would violate the trust that our users have in us.
We have no interest in touching client VMs after they're running.
We promise to keep your machines running smoothly.
If you lose access to your VM, that's on you.</p>
</li>
<li>
Do you offer refunds?
<p>Not now, but email us and we can probably figure something out.</p>
</li>
<li>
Where do the VMs run? Is it on a machine that you guys own/control?
<p>Capsul runs on a server named Baikal which Cyberia built from scratch & mailed to a datacenter
in Georgia called CyberWurx. CyberWurx staff installed it for us in a rack space that
Cyberia pays for. </p>
</li>
<li>
Do you offer support?
<p>Yep, see <a href="/support">our support page</a>.</p>
</li>
<li>
Do you have an SLA?
<p>No, but we normally respond pretty quickly.</p>
</li>
<li>
Will you implement feature X?
<p>Maybe! Email <a href="mailto:ops@cyberia.club">ops@cyberia.club</a> and ask us about it.</p>
How do I use this system?
<p>Please see <a href="https://capsul.org/faq">the official Capsul FAQ
page</a>.</p>
</li>
</ul>
</p>

View File

@ -1,31 +1,26 @@
{% extends 'base.html' %}
{% block content %}
<h1>CAPSUL</h1>
<h1>
<pre>
.-.
/:::\
/::::/
/ `-:/
/ /
\ /
`"`
_ _
_ _ ___ | | ___ ___ ___ | | ___
| | | |/ _ \| |/ _ \ / __/ _ \| |/ _ \
| |_| | (_) | | (_) | (_| (_) | | (_) |
\__, |\___/|_|\___/ \___\___/|_|\___/
|___/
</pre>
<span>Simple, fast, private compute by <a href="https://cyberia.club">cyberia.club</a></span>
<span>Co-operative hosting using <a href="https://cyberia.club">Cyberia</a>'s Capsul</span>
{% endblock %}
{% block subcontent %}
<p>
<ul>
<li>Low friction: simply log in with your email address and fund your account with Credit/Debit or Cryptocurrency</li>
<li>All root disks are backed up at no charge</li>
<li>All storage is fast, local, and solid-state</li>
<li>All network connections are low latency</li>
<li>Supported by amazing volunteers from Cyberia</li>
<li>Upfront prices, no confusing billing</li>
<li>Operated by a Minnesota non-profit organization that will never exploit you</li>
<li>We donate a portion of our proceeds to likeminded hacker groups around the globe</li>
<li>Sign up for an account!</li>
<li>Add some funds!</li>
<li>Create a VPS!</li>
<li>Give your feedback!</li>
</ul>
</p>
{% endblock %}

View File

@ -7,42 +7,17 @@
<h1>CAPSUL TYPES & PRICING</h1>
</div>
<div class="row half-margin">
<table>
<thead>
<tr>
<th>type</th>
<th>monthly*</th>
<th>cpus</th>
<th>mem</th>
<th>ssd</th>
<th>net</th>
</tr>
</thead>
<tbody>
{% for vm_size_key, vm_size in vm_sizes.items() %}
<tr>
<td>{{ vm_size_key }}</td>
<td>${{ vm_size['dollars_per_month'] }}</td>
<td>{{ vm_size['vcpus'] }}</td>
<td>{{ vm_size['memory_mb'] }}</td>
<td>25G</td>
<td>{{ vm_size['bandwidth_gb_per_month'] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<p>
Rates for this service aren't set yet. You can see Cyberia's Capsul pricing
on <a href="https://capsul.org/pricing">their website</a>.
</p>
</div>
<div class="row half-margin">
<div>
<pre>
* net is calculated as a per-month average
* vms are billed for a minimum of 24 hours upon creation
* all VMs come standard with one public IPv4 address
SUPPORTED OPERATING SYSTEMS:
SUPPORTED OPERATING SYSTEMS:
{% for os_id, os in operating_systems.items() %} - {{ os.description }}
{% endfor %}
</pre>
{% for os_id, os in operating_systems.items() %} - {{ os.description }}
{% endfor %}
</pre>
</div>
{% endblock %}

View File

@ -7,20 +7,14 @@
<h1>SUPPORT</h1>
</div>
<div class="row half-margin">
<a href="mailto:support@cyberia.club?subject=Please%20help!">support@cyberia.club</a>
<a href="mailto:yolocolo@doesthisthing.work?subject=Please%20help!">yolocolo@doesthisthing.work</a>
</div>
{% endblock %}
{% block subcontent %}
<p>
Note: We maintain a searchable archive of all support emails at
<a href="https://lists.cyberia.club/~cyberia/support">https://lists.cyberia.club/~cyberia/support</a>
</p>
<p>
If you do not want your mail to appear in a public archive, email <a href="mailto:capsul@cyberia.club?subject=Please%20help!">capsul@cyberia.club</a> instead.
</p>
<p>
Please describe your problem or feature request, and we will do our best to get back to you promptly. Thank you very much.
You can also find us on Matrix: <a
href="https://matrix.to/#/#untitled-hosting.public:autonomic.zone">#untitled-hosting.public:autonomic.zone</a>.
</p>
{% endblock %}

View File

@ -0,0 +1,94 @@
{% extends 'base.html' %}
{% block title %}Account Balance{% endblock %}
{% block content %}
<div class="row third-margin">
<h1>Account Balance: ${{ account_balance }}</h1>
</div>
<div class="half-margin">
{% if has_vms and has_payments and warning_text != "" %}
<div class="row">
<pre class="wrap">{{ warning_text }}</pre>
</div>
{% endif %}
<div class="row">
{% if has_payments %}
<div>
<div class="row third-margin">
<h1>Payments</h1>
</div>
<table>
<thead>
<tr>
<th>amount</th>
<th>date</th>
</tr>
</thead>
<tbody>
{% for payment in payments %}
<tr>
<td class="{{ payment['class_name'] }}">${{ payment["dollars"] }}</td>
<td class="{{ payment['class_name'] }}">{{ payment["created"] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
<ul>
<li>
<h1>PAYMENT OPTIONS</h1>
<ul>
<li>
<a href="/payment/stripe">Add funds with Credit/Debit (stripe)</a>
<ul><li>notice: stripe will load nonfree javascript </li></ul>
</li>
{% if btcpay_enabled %}
<li><a href="/payment/btcpay">Add funds with Bitcoin/Litecoin/Monero (btcpay)</a></li>
{% endif %}
</ul>
</li>
</ul>
</div>
{% if has_vms %}
<div class="row third-margin">
<h1>Capsuls Billed</h1>
</div>
<div class="row">
<table class="small">
<thead>
<tr>
<th>id</th>
<th>created</th>
<th>deleted</th>
<th>$/month</th>
<th>months</th>
<th>$ billed</th>
</tr>
</thead>
<tbody>
{% for vm in vms_billed %}
<tr>
<td>{{ vm["id"] }}</td>
<td>{{ vm["created"] }}</td>
<td>{{ vm["deleted"] }}</td>
<td>${{ vm["dollars_per_month"] }}</td>
<td>{{ vm["months"] }}</td>
<td>${{ vm["dollars"] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
</div>
{% endblock %}
{% block pagesource %}/templates/create-capsul.html{% endblock %}

View File

@ -0,0 +1,60 @@
<html lang="en">
<head>
<!-- Namecoin Address: N2aVL6pHtBp7EtNGb3jpsL2L2NyjBNbiB1 -->
<link href="{{ url_for('static', filename='favicon.yolocolo.ico') }}" rel="icon">
<title>{% block title %}{% endblock %}{% if self.title() %} - {% endif %}Capsul</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta name="Description" content="Cyberia Capsul">
{% block head %}{% endblock %}
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='style.yolocolo.css') }}">
</head>
<body>
<nav>
<div class="row justify-space-between half-margin">
<div>
🦉 <a href="/"><b>YOLOCOLO</b></a>
</div>
<div>
&nbsp;
{% if session["account"] %}
{ {{ session["account"] }} <a href="{{ url_for('auth.logout') }}">Log Out</a> }
{% else %}
<a href="{{ url_for('auth.login') }}">Login</a>
{% endif %}
</div>
</div>
<div class="row justify-center half-margin wrap nav-links">
<a href="/pricing">Pricing</a>
<a href="/faq">FAQ</a>
{% if session["account"] %}
<a href="/console">Capsuls</a>
<a href="/console/ssh">SSH Public Keys</a>
<a href="/console/account-balance">Account Balance</a>
{% endif %}
<a href="/support">Support</a>
</div>
</nav>
{% for message in get_flashed_messages() %}
<div class="flash">{{ message }}</div>
{% endfor %}
{% block custom_flash %}{% endblock %}
<main>
{% block content %}{% endblock %}
</main>
{% block subcontent %}{% endblock %}
<footer>
This server runs <a
href="https://giit.cyberia.club/~forest/capsul-flask">capsul-flask</a> by
Cyberia Computer Club, available under the <a
href="https://creativecommons.org/licenses/by-sa/4.0/">Attribution-ShareAlike
4.0 International</a> licence.<br/><br/>
<a href="https://git.autonomic.zone/3wordchant/capsul-flask/src/branch/yolocolo/capsulflask{% block pagesource %}{% endblock %}">View page source</a>
</footer>
</body>
</html>

View File

@ -0,0 +1,68 @@
{% extends 'base.html' %}
{% block title %}Capsuls{% endblock %}
{% block custom_flash %}
{% if created %}
<div class="flash green">{{ created }} successfully created!</div>
{% endif %}
{% endblock %}
{% block content %}
<div class="row third-margin">
<h1>Capsuls</h1>
</div>
<div class="third-margin">
{% if has_vms %}
<div class="row third-margin justify-end">
<a href="/console/create">Create Capsul</a>
</div>
<div class="row">
<table>
<thead>
<tr>
<th class="heart-icon"></th>
<th>id</th>
<th>size</th>
<th>cpu</th>
<th>mem</th>
<th>ipv4</th>
<th>os</th>
<th>created</th>
</tr>
</thead>
<tbody>
{% for vm in vms %}
<tr>
{% if vm['state'] == 'starting' or vm['state'] == 'stopping' %}
<td class="capsul-status waiting-pulse"></td>
{% elif vm['state'] == 'crashed' or vm['state'] == 'blocked' or vm['state'] == 'stopped' %}
<td class="capsul-status red"></td>
{% elif vm['state'] == 'unknown' %}
<td class="capsul-status-questionmark">?</td>
{% else %}
<td class="capsul-status green"></td>
{% endif %}
<td><a class="no-shadow" href="/console/{{ vm['id'] }}">{{ vm["id"] }}</a></td>
<td>{{ vm["size"] }}</td>
<td class="metrics"><img src="/metrics/cpu/{{ vm['id'] }}/5m/s"/></td>
<td class="metrics"><img src="/metrics/memory/{{ vm['id'] }}/5m/s"/></td>
<td class="{{ vm['ipv4_status'] }}">{{ vm["ipv4"] }}</td>
<td>{{ vm["os"] }}</td>
<td>{{ vm["created"] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="row">
<p>You don't have any Capsuls running. <a href="/console/create">Create one</a> today!</p>
</div>
{% endif %}
</div>
{% endblock %}
{% block pagesource %}/templates/capsuls.html{% endblock %}

View File

@ -0,0 +1,46 @@
{% extends 'base.html' %}
{% block title %}FAQ{% endblock %}
{% block content %}
<div class="row full-margin"><h1>Frequently Asked Questions</h1></div>
{% endblock %}
{% block subcontent %}
<p>
<ul>
<li>
What is this?
<p>
This is a <strong>technical demo</strong> of <a
href="https://giit.cyberia.club/~forest/capsul-flask">Capsul</a>, for the
as-yet-untitled <a href="https://coops.tech">Cotech</a> server hosting
initiative, which you can <a
href="https://community.coops.tech/t/call-for-input-v2-co-op-vps-survey/2802/9">read
about on the Cotech forum</a>.
</p>
</li>
<li>
What do you mean, "technical demo"?
<p>No backups</p>
<p>No service level agreement</p>
<p>"Best effort" support</p>
</li>
<li>
Where can I get this, but, more reliable?
<p>Cyberia, the authors of this platform, run the canonical instance, <a
href="https://capsul.org">Capsul.org</a>, on hardware they own. Please
send them your money! (cash, crypto, or card accepted).</p>
</li>
<li>
How do I use this system?
<p>Please see <a href="https://capsul.org/faq">the official Capsul FAQ
page</a>.</p>
</li>
</ul>
</p>
{% endblock %}
{% block pagesource %}/templates/faq.html{% endblock %}

View File

@ -0,0 +1,28 @@
{% extends 'base.html' %}
{% block content %}
<h1>
<pre>
_ _
_ _ ___ | | ___ ___ ___ | | ___
| | | |/ _ \| |/ _ \ / __/ _ \| |/ _ \
| |_| | (_) | | (_) | (_| (_) | | (_) |
\__, |\___/|_|\___/ \___\___/|_|\___/
|___/
</pre>
<span>Co-operative hosting using <a href="https://cyberia.club">Cyberia</a>'s Capsul</span>
{% endblock %}
{% block subcontent %}
<p>
<ul>
<li>Sign up for an account!</li>
<li>Add some funds!</li>
<li>Create a VPS!</li>
<li>Give your feedback!</li>
</ul>
</p>
{% endblock %}
{% block pagesource %}/templates/index.html{% endblock %}

View File

@ -0,0 +1,23 @@
{% extends 'base.html' %}
{% block title %}Pricing{% endblock %}
{% block content %}
<div class="row third-margin">
<h1>CAPSUL TYPES & PRICING</h1>
</div>
<div class="row half-margin">
<p>
Rates for this service aren't set yet. You can see Cyberia's Capsul pricing
on <a href="https://capsul.org/pricing">their website</a>.
</p>
</div>
<div>
<pre>
SUPPORTED OPERATING SYSTEMS:
{% for os_id, os in operating_systems.items() %} - {{ os.description }}
{% endfor %}
</pre>
</div>
{% endblock %}

View File

@ -0,0 +1,21 @@
{% extends 'base.html' %}
{% block title %}Support{% endblock %}
{% block content %}
<div class="row half-margin">
<h1>SUPPORT</h1>
</div>
<div class="row half-margin">
<a href="mailto:yolocolo@doesthisthing.work?subject=Please%20help!">yolocolo@doesthisthing.work</a>
</div>
{% endblock %}
{% block subcontent %}
<p>
You can also find us on Matrix: <a
href="https://matrix.to/#/#untitled-hosting.public:autonomic.zone">#untitled-hosting.public:autonomic.zone</a>.
</p>
{% endblock %}
{% block pagesource %}/templates/support.html{% endblock %}

36
docker-compose.yml Normal file
View File

@ -0,0 +1,36 @@
---
version: "3.8"
services:
app:
image: 3wordchant/capsul-flask:latest
build: .
volumes:
- "./:/app/code"
- "../tank:/tank"
# - "/var/run/libvirt/libvirt-sock:/var/run/libvirt/libvirt-sock"
depends_on:
- db
ports:
- "5000:5000"
environment:
- "POSTGRES_CONNECTION_PARAMETERS=host=db port=5432 user=capsul password=capsul dbname=capsul"
- SPOKE_MODEL=shell-scripts
#- FLASK_DEBUG=1
- BASE_URL=http://localhost:5000
- ADMIN_PANEL_ALLOW_EMAIL_ADDRESSES=3wc.capsul@doesthisthing.work
- VIRSH_DEFAULT_CONNECT_URI=qemu:///system
# The image uses gunicorn by default, let's override it with Flask's
# built-in development server
command: ["flask", "run", "-h", "0.0.0.0", "-p", "5000"]
db:
image: "postgres:9.6.5-alpine"
volumes:
- "postgres:/var/lib/postgresql/data"
environment:
POSTGRES_USER: capsul
POSTGRES_PASSWORD: capsul
POSTGRES_DB: capsul
volumes:
postgres: