Browse Source

webp images and using-your-own-domain-name-with-greenhouse page

master
forest 2 weeks ago
parent
commit
26ee7d5b11
26 changed files with 279 additions and 25 deletions
  1. +6
    -3
      .gitignore
  2. +2
    -0
      frontend.go
  3. +115
    -0
      frontend/about-dns.gotemplate.html
  4. +3
    -3
      frontend/alpha-profile.gotemplate.html
  5. +1
    -1
      frontend/index-highlight.gotemplate.html
  6. +7
    -7
      frontend/index.gotemplate.html
  7. +1
    -1
      frontend/profile.gotemplate.html
  8. BIN
      frontend/static/favicon.ico
  9. +61
    -4
      frontend/static/greenhouse.css
  10. +51
    -0
      frontend/static/image-sources/generate_webp.sh
  11. BIN
      frontend/static/images/beginner.webp
  12. BIN
      frontend/static/images/custodialcloud.webp
  13. BIN
      frontend/static/images/free.webp
  14. BIN
      frontend/static/images/greenhouse-border.webp
  15. BIN
      frontend/static/images/hybridcloud.webp
  16. BIN
      frontend/static/images/information.webp
  17. BIN
      frontend/static/images/macos.webp
  18. BIN
      frontend/static/images/namecheap-1.webp
  19. BIN
      frontend/static/images/namecheap-2.webp
  20. BIN
      frontend/static/images/namecheap-3.webp
  21. BIN
      frontend/static/images/selfhost.webp
  22. BIN
      frontend/static/images/shine.webp
  23. BIN
      frontend/static/images/tux.webp
  24. BIN
      frontend/static/images/windows.webp
  25. +0
    -6
      frontend/using-your-own-domain-name-with-greenhouse.gotemplate.html
  26. +32
    -0
      frontend_howto.go

+ 6
- 3
.gitignore View File

@ -1,9 +1,12 @@
*.crt
*.key
config.json
favicon.ico
frontend/static/*.png
frontend/static/*.svg
frontend/static/image-sources/*.png
frontend/static/image-sources/*.kra
frontend/static/image-sources/*.psd
frontend/static/image-sources/*.jpg
frontend/static/image-sources/*.jpeg
frontend/static/image-sources/*.svg
threshold/threshold
greenhouse
greenhouse-daemon/caddy


+ 2
- 0
frontend.go View File

@ -86,6 +86,8 @@ func initFrontend(workingDirectory string, config *Config, model *DBModel, backe
app.buildPage(responseWriter, session, highlightContent, pageContent)
})
registerHowtoRoutes(&app)
registerLoginRoutes(&app, emailService)
registerProfileRoutes(&app)


+ 115
- 0
frontend/about-dns.gotemplate.html View File

@ -0,0 +1,115 @@
<div class="horizontal wrap justify-center">
<div class="box pagewidth">
<h2>using your own domain name with greenhouse</h2>
<div>
<p>
If you wish to use your own domain name (lets say it's <code>example.com</code>) with Greenhouse, you must first
create a <code>CNAME</code> resource record pointing to
{{if .Subdomain }}
your personal greenhouse domain <code>{{ .Subdomain }}.{{ .SubdomainDomain }}</code>.
{{else}}
a personal greenhouse domain like <code>my-subdomain.{{ .SubdomainDomain }}</code>.
{{end}}
</p>
<p>
In order to do this, you will need to log into whatever service or system is currently managing your DNS records.
Most of the time this will be a web-based control panel offered by the domain registrar that you paid to register the domain:
<a href="https://namecheap.com">namecheap.com</a>,
<a href="https://gandi.net">gandi.net</a>,
<a href="https://porkbun.com">porkbun.com</a>, and
<a href="https://njal.la">njal.la</a>
are some examples of registrar companies you may have used.
</p>
<p>
Sometimes these companies hide the panel you need to access to create this record under the "advanced" tab.
</p>
<div class="info admonition">
<!--&#9888;&#65039; yellow triangle exclamation point warning emoji-->
<!--&#9888;&#65039; blue info icon emoji-->
<div class="emoji-icon">
<img class="image-small" src="/static/images/information.webp"/>
</div>
<p>
Note that you can only create a <code>CNAME</code> record for a <b>subdomain</b> on your domain,
for example <code>www.example.com</code> or <code>blog.example.com</code>. According to
<a href="https://datatracker.ietf.org/doc/html/rfc1034#section-3.6.2">rfc1034 - domain names</a>,
a <code>CNAME</code> record can't exist on the
<a href="https://stackoverflow.com/questions/55461299/what-is-the-correct-term-for-apex-naked-bare-root-domain-names">
"base", "apex", or "second-level" domain</a> <code>example.com</code>.
</p>
<p>
That specification document was written in 1987, and since then, web developers the world over have yeared for a way
to redirect DNS lookups from an apex domain to somewhere else. Domain name companies have responded to this desire
in many different ways. Some offer a dynamic <code>A</code> record or "<code>ALIAS</code> record" which can point to
a domain name instead of an IP addess.
</p>
<p>
These solutions work somewhat similar to how a <code>CNAME</code> would while sidestepping the limitation.
Some companies like
<a href="https://blog.cloudflare.com/introducing-cname-flattening-rfc-compliant-cnames-at-a-domains-root/">
cloudflare
</a>
misrepresent this "dynamic <code>A</code> record" in thier user interface and refer to it as <code>CNAME</code>,
even though it's not actually a <code>CNAME</code>.
</p>
<p>
Meanwhile, other providers like
<a href="https://www.namecheap.com/support/knowledgebase/article.aspx/9646/2237/how-to-create-a-cname-record-for-your-domain/">
namecheap
</a>
have
<a href="https://serverfault.com/questions/638206/how-does-my-registrar-namecheap-let-me-set-up-a-cname-record-on-the-apex-domai#638215">
rebelled and decided not to follow the specification</a>,
allowing users to create <code>CNAME</code> records on apex domains, even though it might break things.
</p>
<p>
Luckily, namecheap does also offer an <code>ALIAS</code> record type which is much preferred on apex domains as it is guaranteed
to be compatible & should not cause software bugs.
</p>
<p>
As you can see, this is a bit of a nuanced topic. If you want to use your apex domain,
it's probably worth it to research how your DNS provider handles this.
</p>
<p>
The alternative solution might be to simply not use the apex domain; use a subdomain for your <code>CNAME</code>
and then have your provider set up a web-based redirect from the apex domain to the subdomain.
</p>
<p>
For more information see <a href="https://www.isc.org/blogs/cname-at-the-apex-of-a-zone/">
It is often asked, “Why can’t I have a CNAME at the zone apex?”</a> at the
<a href="https://www.isc.org">Internet Systems Consortium</a> blog.
</p>
</div>
<br/>
<br/>
<h3>configuration example: namecheap</h3>
<p>
Here are some screenshots documenting the way the DNS records would be created when using namecheap.
Other DNS providers will probably look somewhat similar.
</p>
<ol>
<li>Navigate to "Advanced DNS" for your domain:<br/><br/>
<img src="/static/images/namecheap-1.webp"/>
<br/>
<br/>
</li>
<li>When configuring a subdomain like <code>www</code>, use a <code>CNAME</code> record:<br/><br/>
<img src="/static/images/namecheap-2.webp"/>
<br/>
<br/>
</li>
<li>When configuring the apex domain (represented as <code>@</code> in DNS software)
use an <code>ALIAS</code> record:<br/><br/>
<img src="/static/images/namecheap-3.webp"/>
<br/>
<br/>
</li>
</ol>
</div>
</div>
</div>

+ 3
- 3
frontend/alpha-profile.gotemplate.html View File

@ -111,7 +111,7 @@
<input type="radio" name="client" value="windows" id="client-windows" checked="checked"></input>
<label class="tab" for="client-windows">
<div class="horizontal align-center">
<img class="os-image" src="static/windows.png"/> windows
<img class="os-image" src="static/images/windows.webp"/> windows
</div>
</label>
<div class="vertical tab-content">
@ -123,7 +123,7 @@
<input type="radio" name="client" value="linux" id="client-linux" checked="checked"></input>
<label class="tab" for="client-linux">
<div class="horizontal align-center">
<img class="os-image" src="static/tux.png"/> linux
<img class="os-image" src="static/images/tux.webp"/> linux
</div>
</label>
<div class="vertical tab-content">
@ -135,7 +135,7 @@
<input type="radio" name="client" value="macos" id="client-macos" checked="checked"></input>
<label class="tab" for="client-macos">
<div class="horizontal align-center">
<img class="os-image" src="static/macos.png"/> mac os
<img class="os-image" src="static/images/macos.webp"/> mac os
</div>
</label>
<div class="vertical tab-content">


+ 1
- 1
frontend/index-highlight.gotemplate.html View File

@ -1,4 +1,4 @@
<img class="image-medium float-right" src="static/greenhouse-border.svg"/>
<img class="image-medium float-right" src="static/images/greenhouse-border.webp"/>
<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,


+ 7
- 7
frontend/index.gotemplate.html View File

@ -1,4 +1,4 @@
<img class="image-medium float-right" src="static/beginner.png"/>
<img class="image-medium float-right" src="static/images/beginner.webp"/>
<h1>what we do</h1>
<p>
Greenhouse enables your own web server (owned by you and running on your computer)
@ -36,7 +36,7 @@
<div class="horizontal flip space-around">
<div class="box">
<h3>self-hosting</h3>
<img class="image-large" src="static/selfhost.png"/>
<img class="image-large expand" src="static/images/selfhost.webp"/>
<p>
True self-hosting ranges from difficult to impossible
for most people. Many of the requirements are either not avaliable or require complex work-arounds.
@ -44,7 +44,7 @@
</div>
<div class="box">
<h3>greenhouse</h3>
<img class="image-large" src="static/hybridcloud.png"/>
<img class="image-large expand" src="static/images/hybridcloud.webp"/>
<p>
Greenhouse provides all of the neccesary network configuration to host a server on the public internet,
but it leaves all of the data storage and web-serving up to your system.<br/><br/>
@ -54,7 +54,7 @@
<div class="box">
<h3>traditional cloud</h3>
<img class="image-large" src="static/custodialcloud.png"/>
<img class="image-large expand" src="static/images/custodialcloud.webp"/>
<p>
Almost all other cloud service providers offer exclusively custodial services,
meaning they technically own all of the data and encryption keys related to your application.
@ -107,7 +107,7 @@
<div class="box">
<h3>&nbsp;<br/>cloud storage</h3>
<div class="box price-box">
<div class="price"><img class="image-small" src="static/free.svg"></div>
<div class="price"><img class="image-small" src="static/images/free.webp"></div>
<ul>
<li>first 50MB of storage</li>
<li>first 50MB of download/month</li>
@ -132,7 +132,7 @@
<div class="box">
<h3>public gateway <br/>for self-hosted servers</h3>
<div class="box price-box">
<div class="price"><img class="image-small" src="static/free.svg"></div>
<div class="price"><img class="image-small" src="static/images/free.webp"></div>
<ul>
<li>first three months</li>
<li>first 10GB of bandwidth</li>
@ -164,7 +164,7 @@
<div class="box">
<h3>&nbsp;<br/>domain names</h3>
<div class="box price-box">
<div class="price"><img class="image-small" src="static/free.svg"></div>
<div class="price"><img class="image-small" src="static/images/free.webp"></div>
<p>*.greenhouseusers.com subdomain</p>
</div>
<div class="box price-box">


+ 1
- 1
frontend/profile.gotemplate.html View File

@ -8,7 +8,7 @@
<input type="radio" name="account" value="status" id="account-status" checked="checked"></input>
<label class="tab" for="account-status">account status</label>
<div class="vertical tab-content">
<img src="/profile/usage_graph.png"/>
<img src="/profile/usage_graph.webp"/>
<p>
{{ .BytesSoFar }} used this month
</p>


BIN
frontend/static/favicon.ico View File

Before After

+ 61
- 4
frontend/static/greenhouse.css View File

@ -39,7 +39,7 @@ header .shine-container {
}
header .shine {
opacity: 1;
background-image: url(shine.png);
background-image: url(images/shine.webp);
background-size: cover;
width: 1.8rem;
height: 1.8rem;
@ -80,15 +80,68 @@ header .session-status {
}
code {
padding: 2px 4px;
font-size: 90%;
color: #c7254e;
background-color: #ce3a642c;
border-radius: 4px;
}
pre code,
pre tt {
padding: 0;
font-size: inherit;
color: #222;
background-color: transparent;
border: 0;
}
/* red-purple inline code links */
code a,
a code {
color: #af148f;
}
code a:hover,
a code:hover {
color: #af148f;
}
.admonition {
margin-left: 10px;
border-left: 8px dashed gray;
padding: 5px 20px;
/* display: flex;
flex-direction: row;
align-items: flex-start; */
}
.admonition.warning {
border-left-color: #ffbb00;
background: #e7d8ae;
}
.admonition.info {
border-left-color: #289eff;
background: #c7dffa;
}
.admonition.info code {
background-color: #e100ff10;
}
.emoji-icon {
margin-right: 20px;
margin-top: 15px ;
float: left;
font-family: sans-serif;
font-size: 60px;
text-shadow: 2px 5px 20px #25202e40, 2px 5px 10px #25202e40, 2px 5px 3px #25202e40;
}
main {
/* background: #0000007e; */
}
.highlight {
color: #eee4dd;
@ -127,6 +180,9 @@ pre.flash.info {
color: #432;
min-height: 20em;
}
.pagewidth {
max-width: 1100px;
}
.float-right {
float: right;
@ -276,6 +332,7 @@ form.vertical .js-form-submit-button {
}
.invalid {
color: red;
}
@ -335,7 +392,7 @@ li {
border: 0.2rem dashed #cba;
z-index: 1;
}
.box img {
.box img.expand {
margin: 0 -6rem;
position: relative;
z-index: 2;


+ 51
- 0
frontend/static/image-sources/generate_webp.sh View File

@ -0,0 +1,51 @@
#!/bin/bash -e
quality="40"
# if [ -z "$quality" ]; then
# echo "first argument (quality level, 1 to 100) is required."
# exit 1
# fi
svgToWebp () {
svgFilename="$1"
pngFilename="../images/$(echo "$svgFilename" | sed 's|.svg|.png|')"
webpFilename="$(echo "$pngFilename" | sed 's|.png|.webp|')"
quality="$2"
sizeArgs=""
if [ ! -z "$3" ] && [ ! -z "$4" ]; then
sizeArgs="-w $3 -h $4"
fi
inkscape --without-gui "$svgFilename" $sizeArgs --export-png "$pngFilename"
cwebp -q "$quality"-m 6 -preset text -alpha_filter best "$pngFilename" -o "$webpFilename"
rm "$pngFilename"
}
pngToWebp () {
pngFilename="$1"
webpFilename="../images/$(echo "$pngFilename" | sed 's|.png|.webp|')"
quality="$2"
preset="$3"
cwebp -q "$quality" -m 6 -preset text -alpha_filter best "$pngFilename" -o "$webpFilename"
}
svgToWebp "greenhouse-border.svg" "$quality" "icon"
svgToWebp "free.svg" "$quality" "icon"
#svgToWebp "logo-wa.svg" "$quality" "120" "105"
pngToWebp "beginner.png" "$quality" "icon"
pngToWebp "custodialcloud.png" "$quality" "text"
pngToWebp "hybridcloud.png" "$quality" "text"
pngToWebp "information.png" "$quality" "icon"
pngToWebp "macos.png" "$quality" "icon"
pngToWebp "namecheap-1.png" "$quality" "text"
pngToWebp "namecheap-2.png" "$quality" "text"
pngToWebp "namecheap-3.png" "$quality" "text"
pngToWebp "selfhost.png" "$quality" "text"
pngToWebp "shine.png" "$quality" "icon"
pngToWebp "tux.png" "$quality" "icon"
pngToWebp "windows.png" "$quality" "icon"

BIN
frontend/static/images/beginner.webp View File

Before After

BIN
frontend/static/images/custodialcloud.webp View File

Before After

BIN
frontend/static/images/free.webp View File

Before After

BIN
frontend/static/images/greenhouse-border.webp View File

Before After

BIN
frontend/static/images/hybridcloud.webp View File

Before After

BIN
frontend/static/images/information.webp View File

Before After

BIN
frontend/static/images/macos.webp View File

Before After

BIN
frontend/static/images/namecheap-1.webp View File

Before After

BIN
frontend/static/images/namecheap-2.webp View File

Before After

BIN
frontend/static/images/namecheap-3.webp View File

Before After

BIN
frontend/static/images/selfhost.webp View File

Before After

BIN
frontend/static/images/shine.webp View File

Before After

BIN
frontend/static/images/tux.webp View File

Before After

BIN
frontend/static/images/windows.webp View File

Before After

+ 0
- 6
frontend/using-your-own-domain-name-with-greenhouse.gotemplate.html View File

@ -1,6 +0,0 @@
If you wish to use your own domain name (<code>example.com</code>) with Greenhouse, you must first<br/>
create a <code>CNAME</code> resource record pointing to <code>{{ .Subdomain }}.{{ .SubdomainDomain }}</code><br/>
Note that you can only create a CNAME record for a subdomain on your domain, for example <code>www.example.com</code>.
So you would probably also want to set up a web redirect to on the base domain

+ 32
- 0
frontend_howto.go View File

@ -0,0 +1,32 @@
package main
import (
"net/http"
)
func registerHowtoRoutes(app *FrontendApp) {
app.handleWithSessionNotRequired(
"/using-your-own-domain-name-with-greenhouse",
func(responseWriter http.ResponseWriter, request *http.Request, session Session) {
templateData := struct {
Subdomain string
SubdomainDomain string
}{
SubdomainDomain: freeSubdomainDomain,
}
if session.TenantId != 0 {
tenant, err := app.Model.GetTenant(session.TenantId)
if err != nil {
app.unhandledError(responseWriter, err)
return
}
templateData.Subdomain = tenant.Subdomain
}
app.buildPageFromTemplate(responseWriter, session, "about-dns.html", templateData)
},
)
}

Loading…
Cancel
Save