Browse Source

putting back the greenhouse logo, fixing layout issues, adding alt text

main
forest 1 month ago
parent
commit
4a66a1f34c
3 changed files with 192 additions and 410 deletions
  1. +96
    -56
      index.html
  2. +70
    -0
      static/greenhouse-border.svg
  3. +26
    -354
      static/greenhouse.css

+ 96
- 56
index.html View File

@ -32,7 +32,7 @@
</header>
<main>
<section class="highlight">
<img class="image-medium float-right" src="static/beginner.png"/>
<img class="image-medium float-right" alt="greenhouse logo" src="static/greenhouse-border.svg"/>
<h1>the easiest way to grow IT yourself</h1>
<p>
Greenhouse is a specialized cloud service designed to make self-hosting your own website, email,
@ -43,8 +43,8 @@
</p>
</section>
<section class="page">
<img class="image-large float-right" src="static/servergarden-logo.webp"/>
<h1>what we do</h1>
<img class="image-medium float-right" alt="cartoon of an older man holding three carrots" src="static/beginner.png"/>
<h1 id="what-we-do">what we do</h1>
<p>
Greenhouse enables your own web server (running on your computer within your own home or business)
to be accessible on the internet in seconds, with no credit card required to get started.<br/><br/>
@ -101,7 +101,7 @@
</p>
<h1>how we do it — what makes greenhouse different</h1>
<h1 id="how-we-do-it">how we do it — what makes greenhouse different</h1>
<p>
Greenhouse provides a network gateway that allows internet users to connect to your server(s).
@ -169,7 +169,7 @@
You don't have to be a tech expert to use it, it's meant to be for everyone.
</p>
<h1>greenhouse is in development</h1>
<h1 id="greenhouse-is-in-development">greenhouse is in development</h1>
<p>
The service isn't done yet. Much of the core functionality is working, but must-have features
like payments, billing, and the CLI (Command Line Interface)
@ -237,68 +237,108 @@
<p>These are some rough notes I have taken on what's completed and what's planned for the future.</p>
<pre class="code" style="display: inline-block;">
- [x] free subdomains feature
- [x] gandi client
- [x] db
- [x] ui
- [ ] public suffix list
- [ ] let's encrypt acme limitations research
<ul class="checklist">
<li class="indeterminate">
greenhouse web application basics
<ul>
<li class="checked"><span>login/register</span></li>
<li class="checked"><span>bandwidth utilization graph</span></li>
<li class="checked"><span>manage API tokens</span></li>
<li class="unchecked"><span>billing alarms and billing limits</span></li>
<li class="unchecked"><span>stripe payments (metered billing)</span></li>
<li class="unchecked"><span>cryptocurrency payments</span></li>
</ul>
</li>
- [ ] pay for what you use shared tunnels
- [x] "elastic" cloud instance scale-up and scale-down automation
- [x] multi-tenant threshold server
- [x] bandwidth metric pipeline
- [x] port range allocation
- [ ] tell a tenants threshold clients that they have been moved to diff servers
- [ ] tunnel health monitoring
- [ ] threshold client certificates tied to Greenhouse API tokens
(certificate "revoked" when API token is disabled or deleted)
<li class="indeterminate">
free subdomains feature
<ul>
<li class="checked"><span>gandi client</span></li>
<li class="checked"><span>stored in database</span></li>
<li class="checked"><span>UI</span></li>
<li class="unchecked"><span>try to add greenhouseusers.com to mozilla public suffix list</span></li>
<li class="unchecked"><span>let's encrypt acme limitations research</span></li>
</ul>
</li>
- [x] greenhouse daemon 😈
- [x] caddy supports TCP, TLS, and HTTPS, each w/ optional HAProxy "PROXY" protocol
- [x] server side tenant info api
- [x] tunnel connectivity test
- [ ] certificate issuance audit log & certificate transparency monitoring
- [ ] certificate issuance test
- [ ] e2e test
<li class="indeterminate">
pay for what you use shared tunnels
<ul>
<li class="checked"><span>"elastic" cloud instance scale-up and scale-down automation</span></li>
<li class="checked"><span>multi-tenant threshold server</span></li>
<li class="checked"><span>bandwidth metric pipeline</span></li>
<li class="checked"><span>port range allocation per tenant, for non-tls protocols like SSH</span></li>
<li class="unchecked"><span>tell a tenants threshold clients that they have been moved to new servers</span></li>
<li class="unchecked"><span>tunnel health monitoring</span></li>
<li class="unchecked"><span>threshold client certificates tied to Greenhouse API tokens (certificate "revoked" when API token is disabled or deleted)</span></li>
</ul>
</li>
- [ ] desktop application
- [x] login
- [x] create tunnels
- [ ] tunnels failed error
- [ ] selector GUIs for ports and folders
- [ ] tray icon
- [ ] installers
- [ ] cross-platform testing
- [ ] code signing
- [ ] advanced tunnel options
- [ ] metrics
- [ ] view logs
- [ ] multi node management support
<li class="indeterminate">
greenhouse daemon 😈
<ul>
<li class="checked"><span>embedded caddy supports TCP, TLS, and HTTPS, each w/ optional HAProxy "PROXY" protocol</span></li>
<li class="checked"><span>greenhouse tenant info api</span></li>
<li class="checked"><span>automatic tunnel connectivity test</span></li>
<li class="checked"><span>port range allocation per tenant, for non-tls protocols like SSH</span></li>
<li class="unchecked"><span>certificate issuance audit log & certificate transparency monitoring</span></li>
<li class="unchecked"><span>automatic certificate issuance test</span></li>
<li class="unchecked"><span>automatic end-to-end test </span></li>
<li class="unchecked"><span>multi-server management support</span></li>
</ul>
</li>
- [ ] CLI
- [ ] login/API token
- [ ] tunnel configuration CRUD operations
- [ ] config files
<li class="indeterminate">
desktop application
<ul>
<li class="checked"><span>login w/ greenhouse API token</span></li>
<li class="checked"><span>create tunnels</span></li>
<li class="unchecked"><span>tunnels failed error handling</span></li>
<li class="unchecked"><span>selector GUIs for ports and folders</span></li>
<li class="unchecked"><span>tray icon</span></li>
<li class="unchecked"><span>installers</span></li>
<li class="unchecked"><span>cross-platform testing</span></li>
<li class="unchecked"><span>code signing</span></li>
<li class="unchecked"><span>advanced tunnel options (HAProxy PROXY protocol, failover stuff, etc)</span></li>
<li class="unchecked"><span>metrics</span></li>
<li class="unchecked"><span>view logs</span></li>
</ul>
</li>
- [ ] support hosting email servers
- [x] threshold forward proxy implementation
- [ ] users can elect to get a dedicated threshold server
<li class="unchecked">
<span>CLI (command line interface)</span>
<ul>
<li class="unchecked"><span>login w/ greenhouse API token</span></li>
<li class="unchecked"><span>tunnel configuration CRUD operations</span></li>
<li class="unchecked"><span>config files</span></li>
</ul>
</li>
- [ ] fully managed DNS feature w/ domain registration
<li class="indeterminate">
<span>support hosting email servers</span>
<ul>
<li class="checked"><span>threshold forward proxy implementation </span></li>
<li class="unchecked"><span>users can elect to get a dedicated threshold server IPv4 address</span></li>
</ul>
</li>
- [ ] metered billing w/ stripe
<li class="unchecked"><span>fully managed DNS feature w/ domain registration</span></li>
<li class="checked"><span>greenhouse.server.garden website</span></li>
<li class="unchecked"><span>authenticate 3rd party domains before allowing threshold to forward for them (defense-in-depth security feature)</span></li>
</ul>
- [x] Greenhouse site
- [ ] support cryptocurrency payments
<h2 id="attribution">Attribution</h2>
- [ ] authorized domains for tenants (defense-in-depth security feature)
</pre>
<p>
Icons made by <a href="https://www.flaticon.com/authors/freepik">Freepik</a>
and aquired from <a href="https://www.flaticon.com/">flaticon.com</a>
</p>
</section>
</main>
<footer>


+ 70
- 0
static/greenhouse-border.svg View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<polygon style="fill:#D5DCED;" points="256,42.221 42.221,230.346 42.221,469.779 469.779,469.779 469.779,230.346 "/>
<polygon style="fill:#FFF082;" points="256,84.977 76.426,243.002 76.426,469.779 435.574,469.779 435.574,243.002 "/>
<polygon style="fill:#FFF8C1;" points="256,127.733 110.63,255.658 110.63,469.779 401.37,469.779 401.37,255.658 "/>
<polygon style="fill:#FFFCE6;" points="256,170.488 144.835,268.314 144.835,469.779 367.165,469.779 367.165,268.314 "/>
<g>
<path style="fill:#9BF57D;" d="M126.564,263.383c0,0,58.33,7.912,89.163,38.745c17.029,17.029,19.547,42.12,5.625,56.042
s-39.014,11.404-56.042-5.625C134.476,321.712,126.564,263.383,126.564,263.383z"/>
<path style="fill:#9BF57D;" d="M367.165,238.898c0,0-48.061,6.519-73.466,31.924c-14.031,14.031-16.106,34.705-4.634,46.176
c11.471,11.471,32.145,9.397,46.176-4.634C360.646,286.958,367.165,238.898,367.165,238.898z"/>
</g>
<g>
<path style="fill:#8CE16E;" d="M165.309,352.546c17.03,17.029,42.12,19.547,56.043,5.625l-94.787-94.787
C126.564,263.383,134.476,321.712,165.309,352.546z"/>
<path style="fill:#8CE16E;" d="M289.065,316.998l78.1-78.101c0,0-48.061,6.519-73.465,31.924
C279.669,284.853,277.593,305.526,289.065,316.998z"/>
</g>
<path d="M503.983,461.762h-26.188V230.346c0-2.303-0.991-4.497-2.72-6.018L261.296,36.203c-3.027-2.665-7.565-2.665-10.592,0
L36.926,224.329c-1.731,1.522-2.721,3.714-2.721,6.018v231.415H8.017c-4.427,0-8.017,3.589-8.017,8.017
c0,4.427,3.589,8.017,8.017,8.017h495.967c4.427,0,8.017-3.589,8.017-8.017C512,465.351,508.411,461.762,503.983,461.762z
M50.238,233.971L256,52.9l205.762,181.071v227.791h-18.171v-218.76c0-2.303-0.991-4.497-2.72-6.018L261.296,78.959
c-3.028-2.665-7.563-2.665-10.592,0L71.131,236.984c-1.729,1.522-2.72,3.714-2.72,6.018v218.76H50.238V233.971z M264.017,392.821
c0-0.001,0-0.003,0-0.005v-21.501c0-11.563,4.503-22.435,12.679-30.611l13.093-13.093c5.403,3.189,11.646,4.764,18.122,4.764
c11.407,0,23.528-4.872,32.999-14.342c27.007-27.007,33.918-75.986,34.199-78.057c0.336-2.48-0.506-4.976-2.276-6.746
c-1.77-1.77-4.268-2.61-6.746-2.276c-2.072,0.281-51.051,7.193-78.057,34.199c-14.847,14.847-18.381,36.196-9.576,51.118
l-13.095,13.095c-11.205,11.204-17.376,26.102-17.376,41.948v2.15l-15.873-15.873c4.894-7.607,7.018-16.912,6.014-26.929
c-1.242-12.377-7.161-24.427-16.666-33.932c-32.28-32.28-90.28-39.83-92.733-40.135c-2.458-0.308-4.912,0.538-6.659,2.286
s-2.592,4.206-2.286,6.659c0.306,2.453,7.855,60.453,40.135,92.733c9.506,9.506,21.556,15.425,33.932,16.666
c1.63,0.164,3.24,0.245,4.828,0.245c8.173,0,15.735-2.154,22.106-6.253l27.203,27.208v65.623H84.443V246.626L256,95.655
l171.557,150.972v215.135H264.017V392.821z M299.367,276.491c16.029-16.028,42.665-24.045,57.686-27.481
c-3.436,15.021-11.453,41.658-27.481,57.686c-8.264,8.263-19.26,11.445-27.723,8.855l28.228-28.227
c3.131-3.131,3.131-8.207,0-11.337c-3.131-3.131-8.207-3.131-11.337,0l-28.227,28.227
C287.923,295.751,291.105,284.753,299.367,276.491z M184.708,310.19c-3.131-3.131-8.207-3.131-11.337,0
c-3.131,3.131-3.131,8.207,0,11.337l35.58,35.58c-3.968,1.716-8.567,2.379-13.505,1.882c-8.706-0.873-17.299-5.153-24.195-12.051
c-20.616-20.617-30.018-55.053-33.64-72.519c17.451,3.606,51.843,12.983,72.509,33.649c6.898,6.898,11.177,15.49,12.051,24.195
c0.496,4.938-0.168,9.538-1.882,13.505L184.708,310.19z"/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

+ 26
- 354
static/greenhouse.css View File

@ -66,7 +66,7 @@ p {
a {
font-weight: 600;
color: #66811a;
color: #58740b;
}
header .session-status,
header .session-status a {
@ -90,13 +90,13 @@ header .session-status {
margin-left: 1em;
}
.code a {
color: #6a46a5;
color: #4f327e;
}
code {
padding: 2px 4px;
font-size: 90%;
color: #c75825;
color: #8b2c00;
background-color: #f9f2f4;
border-radius: 4px;
}
@ -119,24 +119,6 @@ main {
color: #b0e226;
}
pre.flash {
border: 2px solid gray;
font-weight: bold;
padding: 2em;
border-radius: 8px;
font-size: 0.8em;
}
pre.flash.error {
border-color: #5e2416;
background: #da9871;
color: #5e2416;
}
pre.flash.info {
border-color: #000000aa;
background: #ffffff60;
color: #12496e;
}
.page {
@ -182,109 +164,16 @@ pre.flash.info {
align-items: flex-start;
}
.money-unit {
margin-right: 0.3em;
}
input,
.js-form-submit-button {
box-sizing: content-box;
border-radius: 4px;
border: 1px solid #ccc;
padding: 0.5rem;
color: #333;
font-size: 1em;
}
input:focus {
border: 2px solid #029dfd;
padding: calc(0.5rem - 1px);
}
input.right-align {
text-align: right;
}
input.short {
width: 10em;
}
input.subdomain {
padding-right: 0;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Firefox */
input[type=number] {
-moz-appearance: textfield;
}
/* roughly copy and pasted from the firefox user agent style sheet on linux :D */
.fake-text-input {
text-rendering: auto;
color: rgb(58, 58, 58);
display: inline-block;
text-align: start;
-webkit-appearance: textfield;
background-color: white;
margin: 0em;
font: 400 13.3333px Arial;
padding: 7px;
border-radius: 3px;
box-shadow: inset 0 0 3px 0px rgba(0,0,0,0.1);
border: 1px solid #ccc;
min-width: 18em;
}
label {
margin-right: 1em;
}
form.vertical input,
form.horizontal.wrap input,
form.vertical .js-form-submit-button {
margin-top: 0.4rem;
margin-bottom: 0.4rem;
}
.js-form-submit-button {
padding: 0.25em 1em;
cursor: pointer;
display: none;
}
.form-footer {
font-size: 0.85em;
padding-top: 1rem;
}
.fine-print {
font-size: 0.7em;
}
.api-token-form {
background-color: #dfd5ca;
border-radius: 1em;
padding: 0.7em;
}
.api-token {
border-bottom: 1px solid #44332277;
margin: 0.5em;
padding: 0.05em;
}
.new-api-token {
background-color: #619d00;
color: white;
border-radius: 0.5em;
padding: 0.5em;
border-bottom: 0;
line-height: 2em;
font-weight: bold;
}
@media screen and (max-width: 900px) {
.horizontal.flip {
@ -344,263 +233,46 @@ pre {
z-index: 2;
}
.tab-container {
margin: 1rem;
display: grid;
}
.tab-container input[type="radio"] {
display: none;
}
.tab-container > label:nth-of-type(1) {
grid-column: 1 / 2;
}
.tab-container > label:nth-of-type(2) {
grid-column: 2 / 4;
}
.tab-container > label:nth-of-type(3) {
grid-column: 4 / 5;
}
.tab-container > label {
margin: 0;
grid-row: 1 / 2;
border-top: 2px solid #00000000;
padding: 1rem;
border-bottom: 2px solid #c4c4c4;
cursor: pointer;
text-align: center;
white-space: nowrap;
color: #432;
text-decoration: none;
font-family: 'Nunito',-apple-system,system-ui,BlinkMacSystemFont,"Ubuntu",Roboto,"Segoe UI",sans-serif;
font-weight: bold;
font-size: 1.1em;
}
.tab-container input[type="radio"]:checked + label {
border-top: 2px solid #8a7232;
background: white;
border-bottom: 2px solid #00000000;
box-shadow: 0.1rem 0.5rem 1rem 0 #00000020;
}
.tab-container input[type="radio"]:checked + label + .tab-content {
display: block;
}
.tab-container.two-tabs .tab-content {
grid-column: 1 / 4;
}
.tab-container.three-tabs .tab-content {
grid-column: 1 / 5;
}
.tab-content {
grid-row: 2 / 3;
display: none;
position: relative;
padding: 1rem;
z-index: 1;
background: white;
box-shadow: 0.1rem 0.5rem 1rem 0 #00000020;
}
/* this makes the tab-content for the selected tab visible */
input[type="radio"].tab:checked+label {
display: block;
}
@media screen and (max-width: 1150px) and (min-width: 901px) {
.service-pricing .box {
border-radius: 0;
margin-left: -0.1rem;
margin-right: -0.1rem;
}
.service-pricing .box:first-child {
border-top-left-radius: 1rem;
border-bottom-left-radius: 1rem;
}
.service-pricing .box:nth-child(2) {
border-bottom-right-radius: 1rem;
border-bottom-left-radius: 1rem;
}
.service-pricing .box:last-child {
border-top-right-radius: 1rem;
border-bottom-right-radius: 1rem;
}
.service-pricing .box.price-box {
border-radius: 0.5rem;
}
}
.box.price-box {
border-radius: 0.5rem;
min-width: 11rem;
padding: 1rem;
padding-bottom: 0rem;
margin-left: -1rem;
margin-right: -1rem;
box-shadow: 0 0.5rem 1rem 0 #00000070;
border: 2px solid #ccc;
width: 100%;
}
ul.checklist {
.price {
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 1.6rem;
padding: 3em;
padding-right: 0;
background-color: #bbb;
border-radius: 6px;
color: #444;
}
.big-price {
font-size: 3.6rem;
ul.checklist > li {
margin-bottom: 1em;
}
.med-price {
font-size: 2.6rem;
ul.checklist, ul.checklist li {
list-style-type: '- ';
font-family: monospace;
white-space: nowrap;
}
.price-box ul {
margin-left: -1rem;
align-self: baseline;
ul.checklist li span {
display: inline-block;
white-space: normal;
padding-right: 40px;
vertical-align: top;
}
.admin-box {
border-radius: 0.5rem;
min-width: 11rem;
padding: 1rem;
padding-bottom: 0rem;
box-shadow: 0 0.5rem 1rem 0 #00000070;
border: 2px solid #ccc;
ul.checklist li.checked::before {
content: '[x] ';
}
.admin-box form {
display: inline;
ul.checklist li.unchecked::before {
content: '[ ] ';
}
.instance-group {
min-height: 100px;
width: 100%;
border: 3px dashed rgb(173, 230, 109);
display: flex;
flex-wrap: wrap;
flex-direction: row;
justify-content: flex-start;
align-content: flex-start;
ul.checklist li.indeterminate::before {
content: '[-] ';
}
.instance-group>h4,
.instance-group>h3,
.instance-group>h5 {
width: 100%;
text-align: center;
}
.instance {
width: 100px;
height: 120px;
margin: 10px;
padding: 10px;
border-radius: 0.3em;
display: flex;
flex-direction: column;
box-sizing: content-box;
}
.instance.healthy {
background-color: rgb(102, 241, 176);
border: 1px solid rgb(56, 161, 165);
}
.instance.unhealthy {
background-color: rgb(255, 116, 92);
border: 1px solid rgb(165, 56, 74);
}
.instance-name,
.instance-ip {
background-color: white;
color: #333;
margin-bottom: 5px;
font-size: 11px;
white-space: nowrap;
overflow: hidden;
}
.instance-content {
display: flex;
flex-direction: row;
justify-content: flex-end;
flex-grow: 1;
box-sizing: content-box;
max-height: calc(100% - 40px);
}
.current-tenants, .pinned-tenants {
display: inline-flex;
writing-mode: vertical-lr;
flex-wrap: wrap;
align-content: flex-start;
margin-right: 5px;
padding: 2px;
min-width: 10px;
min-height: 100%;
}
.current-tenants {
border: 1px solid rgb(51, 57, 116);
}
.pinned-tenants {
border: 1px dashed gray;
}
.tenant {
writing-mode: horizontal-tb;
color: white;
border-radius: 5px;
padding: 3px;
font-size: 10px;
}
.thermometer {
background-color: gray;
min-height: 100%;
width: 6px;
padding: 2px;
margin-right: 5px;
display: flex;
flex-direction: column-reverse;
}
.thermometer.projected {
margin-right: 0;
}
.marker {
display: block;
}
.delete-button {
border: 2px solid red;
color: #400;
background-color: #fcc;
border-radius: 4px;
outline: 0;
padding: 0.2em;
}

Loading…
Cancel
Save