Merge branch 'master' of code.ungleich.ch:ungleich-public/ungleich-staticcms

This commit is contained in:
Nico Schottelius 2020-01-29 14:39:59 +01:00
commit 96fade4d1c
39 changed files with 1663 additions and 64 deletions

39
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,39 @@
stages:
- build
- deploy
image: debian:latest
variables:
BUILDDIR: "build/"
build:
stage: build
before_script:
- apt-get update
- apt-get install -y make lektor imagemagick
script:
- make build
artifacts:
expire_in: 12 hours
paths:
- "build/"
deploy:
stage: deploy
only:
- master
environment:
name: production
url: https://ungleich.ch/
before_script:
# Install dependencies
- apt-get update
- apt-get install -y make openssh-client rsync
# Configure the SSH Agent
- eval $(ssh-agent -s)
- echo "$CD_SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
- mkdir -p ~/.ssh
- echo "$CD_SSH_SERVER_HOSTKEYS" > ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
script:
- make deploy

View file

@ -1,4 +1,4 @@
BUILDDIR=../ungleich-staticcms-build
BUILDDIR?=../ungleich-staticcms-build
DESTINATION=ungleichstatic@staticweb.ungleich.ch:/home/services/www/ungleichstatic/staticcms.ungleich.ch/www/u/
all: publish
@ -6,8 +6,11 @@ all: publish
pull:
git pull
publish: pull build permissions
publish: pull build deploy
deploy: permissions
rsync -av --delete --exclude .lektor/ $(BUILDDIR)/u/ $(DESTINATION)
rsync -av --delete $(BUILDDIR)/sitemap.xml $(DESTINATION)
permissions: build
find $(BUILDDIR) -type f -exec chmod 0644 {} \;

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

BIN
assets/u/image/pizol.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

View file

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.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 106.3 28.3" style="enable-background:new 0 0 106.3 28.3;" xml:space="preserve">
<style type="text/css">
.st0{fill:#050505;}
</style>
<g>
<path class="st0" d="M29.8,24.9c0-0.4,0.1-0.8,0.4-1.2c0.3-0.4,0.7-0.8,1.3-1.1v-0.1c-0.3-0.2-0.5-0.4-0.8-0.7
c-0.2-0.3-0.3-0.7-0.3-1.1c0-0.3,0.1-0.7,0.3-1.1c0.2-0.4,0.5-0.7,0.9-0.9v-0.1c-0.4-0.3-0.7-0.6-1-1.1c-0.3-0.5-0.4-1-0.4-1.6
c0-0.6,0.1-1.1,0.3-1.6c0.2-0.5,0.5-0.9,0.9-1.2c0.4-0.3,0.8-0.6,1.4-0.8c0.5-0.2,1.1-0.3,1.6-0.3c0.6,0,1.1,0.1,1.6,0.3h4.4V14H38
c0.2,0.2,0.4,0.5,0.6,0.9c0.2,0.3,0.3,0.7,0.3,1.1c0,0.6-0.1,1.1-0.3,1.5c-0.2,0.5-0.5,0.8-0.9,1.1c-0.4,0.3-0.8,0.5-1.3,0.7
c-0.5,0.2-1.1,0.2-1.6,0.2c-0.3,0-0.5,0-0.8-0.1c-0.3-0.1-0.6-0.1-0.9-0.3c-0.5,0.3-0.7,0.7-0.7,1.1c0,0.4,0.2,0.7,0.5,0.9
c0.4,0.2,0.9,0.3,1.6,0.3h2.3c1.4,0,2.4,0.2,3.1,0.6c0.7,0.4,1,1.1,1,2c0,0.5-0.1,1-0.4,1.4c-0.3,0.5-0.7,0.8-1.2,1.2
c-0.5,0.3-1.2,0.6-1.9,0.8c-0.7,0.2-1.6,0.3-2.5,0.3c-1.5,0-2.7-0.2-3.6-0.7C30.2,26.6,29.8,25.9,29.8,24.9z M31.6,24.7
c0,0.5,0.3,0.9,0.8,1.2c0.6,0.3,1.4,0.5,2.4,0.5c0.6,0,1.1-0.1,1.5-0.2c0.5-0.1,0.9-0.3,1.2-0.4c0.3-0.2,0.6-0.4,0.8-0.6
c0.2-0.2,0.3-0.5,0.3-0.7c0-0.5-0.2-0.8-0.6-0.9c-0.4-0.2-1-0.2-1.7-0.2h-1.9c-0.3,0-0.6,0-0.9,0c-0.3,0-0.5-0.1-0.7-0.1
c-0.4,0.2-0.7,0.5-0.9,0.8C31.7,24.1,31.6,24.4,31.6,24.7z M34.6,18.3c0.6,0,1.1-0.2,1.6-0.6c0.4-0.4,0.7-1,0.7-1.7
c0-0.7-0.2-1.3-0.7-1.7c-0.4-0.4-1-0.6-1.6-0.6c-0.6,0-1.1,0.2-1.6,0.6c-0.4,0.4-0.7,1-0.7,1.7c0,0.7,0.2,1.3,0.7,1.7
C33.5,18.1,34,18.3,34.6,18.3z"/>
</g>
<path class="st0" d="M13.4,23.3h-1.8l-0.2-1.8h-0.1c-0.5,0.6-1.1,1.1-1.8,1.5c-0.6,0.4-1.4,0.6-2.2,0.6c-1.3,0-2.3-0.4-2.9-1.1
c-0.6-0.8-0.9-1.9-0.9-3.3v-5.5l-2.9-0.1l5.2-2l0,1.5v5.8c0,1,0.2,1.7,0.5,2.2c0.3,0.5,0.9,0.7,1.8,0.7c0.6,0,1.1-0.1,1.6-0.4
c0.5-0.3,1-0.7,1.5-1.4v-7.6h2.2L13.4,23.3L13.4,23.3z"/>
<path class="st0" d="M17.1,12.3h1.8l0.2,1.8h0.1c0.6-0.6,1.2-1.1,1.8-1.5c0.6-0.4,1.4-0.6,2.3-0.6c1.3,0,2.2,0.4,2.8,1.1
c0.6,0.8,0.9,1.9,0.9,3.3v6.8h-2.2v-6.5c0-1-0.2-1.7-0.5-2.1c-0.3-0.5-0.9-0.7-1.8-0.7c-0.6,0-1.1,0.1-1.6,0.4
c-0.5,0.3-1,0.7-1.6,1.3v7.6h-2.2L17.1,12.3L17.1,12.3L17.1,12.3z"/>
<path class="st0" d="M51.9,17.8c0-0.9,0.2-1.7,0.5-2.4c0.3-0.7,0.7-1.3,1.3-1.8c0.5-0.5,1.1-0.9,1.8-1.2c0.7-0.3,1.4-0.4,2.1-0.4
c0.8,0,1.5,0.1,2.2,0.4c0.6,0.3,1.2,0.6,1.6,1.1c0.4,0.5,0.8,1,1,1.6c0.2,0.6,0.3,1.3,0.3,2.1c0,0.2,0,0.4,0,0.6
c0,0.2,0,0.4-0.1,0.5h-8.3c0.1,1.1,0.5,1.9,1.2,2.5c0.7,0.6,1.6,0.9,2.8,0.9c0.6,0,1.2-0.1,1.7-0.2c0.5-0.2,1-0.4,1.5-0.7l0.8,1.4
c-0.6,0.4-1.2,0.7-1.9,0.9c-0.7,0.2-1.5,0.4-2.4,0.4c-0.8,0-1.6-0.1-2.3-0.4c-0.7-0.3-1.4-0.6-1.9-1.1c-0.5-0.5-1-1.1-1.3-1.8
C52.1,19.5,51.9,18.7,51.9,17.8z M60.6,16.8c0-1-0.3-1.8-0.8-2.3c-0.5-0.5-1.2-0.8-2.2-0.8c-0.8,0-1.6,0.3-2.2,0.8
c-0.6,0.5-1,1.3-1.2,2.3H60.6z"/>
<path class="st0" d="M70,11.9l0,11.6h-2.2v-8.5h-4.2L70,11.9z M68.7,9.7c-0.5,0-0.9-0.1-1.2-0.4C67.2,9,67,8.6,67,8.1
c0-0.5,0.2-0.9,0.5-1.2c0.3-0.3,0.7-0.4,1.2-0.4c0.5,0,0.9,0.1,1.2,0.4c0.3,0.3,0.5,0.7,0.5,1.2c0,0.5-0.2,0.9-0.5,1.2
C69.6,9.5,69.2,9.7,68.7,9.7z"/>
<path class="st0" d="M73.1,18c0-0.9,0.2-1.7,0.5-2.5c0.3-0.7,0.8-1.3,1.4-1.8c0.6-0.5,1.2-0.9,2-1.1c0.7-0.3,1.5-0.4,2.4-0.4
c0.9,0,1.7,0.2,2.4,0.5c0.7,0.3,1.2,0.7,1.7,1.1l-1.1,1.4c-0.4-0.4-0.9-0.6-1.4-0.8c-0.5-0.2-1-0.3-1.5-0.3c-0.6,0-1.1,0.1-1.6,0.3
c-0.5,0.2-0.9,0.5-1.3,0.8c-0.4,0.3-0.6,0.8-0.8,1.3c-0.2,0.5-0.3,1-0.3,1.6c0,0.6,0.1,1.1,0.3,1.6c0.2,0.5,0.5,0.9,0.8,1.3
c0.4,0.3,0.8,0.6,1.3,0.8c0.5,0.2,1,0.3,1.6,0.3c0.7,0,1.3-0.1,1.8-0.4c0.5-0.3,1-0.6,1.5-0.9l0.9,1.4c-0.6,0.5-1.3,1-2.1,1.3
c-0.8,0.3-1.5,0.4-2.3,0.4c-0.9,0-1.7-0.1-2.4-0.4c-0.7-0.3-1.4-0.6-1.9-1.1c-0.5-0.5-1-1.1-1.3-1.8C73.2,19.8,73.1,19,73.1,18z"/>
<path class="st0" d="M83.7,7.6l4.7-2.3v6.5l-0.1,2.5c0.6-0.6,1.2-1.1,1.8-1.4c0.6-0.4,1.4-0.6,2.3-0.6c1.3,0,2.2,0.4,2.8,1.1
c0.6,0.8,0.9,1.9,0.9,3.3v6.8h-2.2V17c0-1-0.2-1.7-0.5-2.1c-0.3-0.5-0.9-0.7-1.8-0.7c-0.6,0-1.1,0.1-1.6,0.4c-0.5,0.3-1,0.7-1.6,1.3
v7.6h-2.2l0-16L83.7,7.6z"/>
<g>
<polygon class="st0" points="96.4,2.6 95.7,4.2 105,4.2 105.8,2.6 "/>
<polygon class="st0" points="95.7,6.1 94.9,7.7 104.3,7.7 105,6.1 "/>
<polygon class="st0" points="97.5,9.6 101.8,0.4 103.5,0.5 99.2,9.6 "/>
</g>
<g>
<path class="st0" d="M46.3,19.7c0,0.7,0.2,1.3,0.6,1.6c0.4,0.3,0.9,0.5,1.4,0.5c0.3,0,0.6,0,0.9-0.1c0.3-0.1,0.6-0.2,1-0.3l0.5,1.6
c-0.2,0.1-0.5,0.2-0.7,0.2c-0.2,0.1-0.5,0.1-0.7,0.2c-0.2,0.1-0.5,0.1-0.7,0.1c-0.3,0-0.5,0.1-0.8,0.1c-1.2,0-2.1-0.3-2.7-1
c-0.6-0.7-0.9-1.7-0.9-3V5.1h-3.5l5.6-4"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View file

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.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 106.3 28.3" style="enable-background:new 0 0 106.3 28.3;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
</style>
<g>
<path class="st0" d="M29.8,24.9c0-0.4,0.1-0.8,0.4-1.2c0.3-0.4,0.7-0.8,1.3-1.1v-0.1c-0.3-0.2-0.5-0.4-0.8-0.7
c-0.2-0.3-0.3-0.7-0.3-1.1c0-0.3,0.1-0.7,0.3-1.1c0.2-0.4,0.5-0.7,0.9-0.9v-0.1c-0.4-0.3-0.7-0.6-1-1.1c-0.3-0.5-0.4-1-0.4-1.6
c0-0.6,0.1-1.1,0.3-1.6c0.2-0.5,0.5-0.9,0.9-1.2c0.4-0.3,0.8-0.6,1.4-0.8c0.5-0.2,1.1-0.3,1.6-0.3c0.6,0,1.1,0.1,1.6,0.3h4.4V14H38
c0.2,0.2,0.4,0.5,0.6,0.9c0.2,0.3,0.3,0.7,0.3,1.1c0,0.6-0.1,1.1-0.3,1.5c-0.2,0.5-0.5,0.8-0.9,1.1c-0.4,0.3-0.8,0.5-1.3,0.7
c-0.5,0.2-1.1,0.2-1.6,0.2c-0.3,0-0.5,0-0.8-0.1c-0.3-0.1-0.6-0.1-0.9-0.3c-0.5,0.3-0.7,0.7-0.7,1.1c0,0.4,0.2,0.7,0.5,0.9
c0.4,0.2,0.9,0.3,1.6,0.3h2.3c1.4,0,2.4,0.2,3.1,0.6c0.7,0.4,1,1.1,1,2c0,0.5-0.1,1-0.4,1.4c-0.3,0.5-0.7,0.8-1.2,1.2
c-0.5,0.3-1.2,0.6-1.9,0.8c-0.7,0.2-1.6,0.3-2.5,0.3c-1.5,0-2.7-0.2-3.6-0.7C30.2,26.6,29.8,25.9,29.8,24.9z M31.6,24.7
c0,0.5,0.3,0.9,0.8,1.2c0.6,0.3,1.4,0.5,2.4,0.5c0.6,0,1.1-0.1,1.5-0.2c0.5-0.1,0.9-0.3,1.2-0.4c0.3-0.2,0.6-0.4,0.8-0.6
c0.2-0.2,0.3-0.5,0.3-0.7c0-0.5-0.2-0.8-0.6-0.9c-0.4-0.2-1-0.2-1.7-0.2h-1.9c-0.3,0-0.6,0-0.9,0c-0.3,0-0.5-0.1-0.7-0.1
c-0.4,0.2-0.7,0.5-0.9,0.8C31.7,24.1,31.6,24.4,31.6,24.7z M34.6,18.3c0.6,0,1.1-0.2,1.6-0.6c0.4-0.4,0.7-1,0.7-1.7
c0-0.7-0.2-1.3-0.7-1.7c-0.4-0.4-1-0.6-1.6-0.6c-0.6,0-1.1,0.2-1.6,0.6c-0.4,0.4-0.7,1-0.7,1.7c0,0.7,0.2,1.3,0.7,1.7
C33.5,18.1,34,18.3,34.6,18.3z"/>
</g>
<path class="st0" d="M13.4,23.3h-1.8l-0.2-1.8h-0.1c-0.5,0.6-1.1,1.1-1.8,1.5c-0.6,0.4-1.4,0.6-2.2,0.6c-1.3,0-2.3-0.4-2.9-1.1
c-0.6-0.8-0.9-1.9-0.9-3.3v-5.5l-2.9-0.1l5.2-2l0,1.5v5.8c0,1,0.2,1.7,0.5,2.2c0.3,0.5,0.9,0.7,1.8,0.7c0.6,0,1.1-0.1,1.6-0.4
c0.5-0.3,1-0.7,1.5-1.4v-7.6h2.2L13.4,23.3L13.4,23.3z"/>
<path class="st0" d="M17.1,12.3h1.8l0.2,1.8h0.1c0.6-0.6,1.2-1.1,1.8-1.5c0.6-0.4,1.4-0.6,2.3-0.6c1.3,0,2.2,0.4,2.8,1.1
c0.6,0.8,0.9,1.9,0.9,3.3v6.8h-2.2v-6.5c0-1-0.2-1.7-0.5-2.1c-0.3-0.5-0.9-0.7-1.8-0.7c-0.6,0-1.1,0.1-1.6,0.4
c-0.5,0.3-1,0.7-1.6,1.3v7.6h-2.2L17.1,12.3L17.1,12.3L17.1,12.3z"/>
<path class="st0" d="M51.9,17.8c0-0.9,0.2-1.7,0.5-2.4c0.3-0.7,0.7-1.3,1.3-1.8c0.5-0.5,1.1-0.9,1.8-1.2c0.7-0.3,1.4-0.4,2.1-0.4
c0.8,0,1.5,0.1,2.2,0.4c0.6,0.3,1.2,0.6,1.6,1.1c0.4,0.5,0.8,1,1,1.6c0.2,0.6,0.3,1.3,0.3,2.1c0,0.2,0,0.4,0,0.6
c0,0.2,0,0.4-0.1,0.5h-8.3c0.1,1.1,0.5,1.9,1.2,2.5c0.7,0.6,1.6,0.9,2.8,0.9c0.6,0,1.2-0.1,1.7-0.2c0.5-0.2,1-0.4,1.5-0.7l0.8,1.4
c-0.6,0.4-1.2,0.7-1.9,0.9c-0.7,0.2-1.5,0.4-2.4,0.4c-0.8,0-1.6-0.1-2.3-0.4c-0.7-0.3-1.4-0.6-1.9-1.1c-0.5-0.5-1-1.1-1.3-1.8
C52.1,19.5,51.9,18.7,51.9,17.8z M60.6,16.8c0-1-0.3-1.8-0.8-2.3c-0.5-0.5-1.2-0.8-2.2-0.8c-0.8,0-1.6,0.3-2.2,0.8
c-0.6,0.5-1,1.3-1.2,2.3H60.6z"/>
<path class="st0" d="M70,11.9l0,11.6h-2.2v-8.5h-4.2L70,11.9z M68.7,9.7c-0.5,0-0.9-0.1-1.2-0.4C67.2,9,67,8.6,67,8.1
c0-0.5,0.2-0.9,0.5-1.2c0.3-0.3,0.7-0.4,1.2-0.4c0.5,0,0.9,0.1,1.2,0.4c0.3,0.3,0.5,0.7,0.5,1.2c0,0.5-0.2,0.9-0.5,1.2
C69.6,9.5,69.2,9.7,68.7,9.7z"/>
<path class="st0" d="M73.1,18c0-0.9,0.2-1.7,0.5-2.5c0.3-0.7,0.8-1.3,1.4-1.8c0.6-0.5,1.2-0.9,2-1.1c0.7-0.3,1.5-0.4,2.4-0.4
c0.9,0,1.7,0.2,2.4,0.5c0.7,0.3,1.2,0.7,1.7,1.1l-1.1,1.4c-0.4-0.4-0.9-0.6-1.4-0.8c-0.5-0.2-1-0.3-1.5-0.3c-0.6,0-1.1,0.1-1.6,0.3
c-0.5,0.2-0.9,0.5-1.3,0.8c-0.4,0.3-0.6,0.8-0.8,1.3c-0.2,0.5-0.3,1-0.3,1.6c0,0.6,0.1,1.1,0.3,1.6c0.2,0.5,0.5,0.9,0.8,1.3
c0.4,0.3,0.8,0.6,1.3,0.8c0.5,0.2,1,0.3,1.6,0.3c0.7,0,1.3-0.1,1.8-0.4c0.5-0.3,1-0.6,1.5-0.9l0.9,1.4c-0.6,0.5-1.3,1-2.1,1.3
c-0.8,0.3-1.5,0.4-2.3,0.4c-0.9,0-1.7-0.1-2.4-0.4c-0.7-0.3-1.4-0.6-1.9-1.1c-0.5-0.5-1-1.1-1.3-1.8C73.2,19.8,73.1,19,73.1,18z"/>
<path class="st0" d="M83.7,7.6l4.7-2.3v6.5l-0.1,2.5c0.6-0.6,1.2-1.1,1.8-1.4c0.6-0.4,1.4-0.6,2.3-0.6c1.3,0,2.2,0.4,2.8,1.1
c0.6,0.8,0.9,1.9,0.9,3.3v6.8h-2.2V17c0-1-0.2-1.7-0.5-2.1c-0.3-0.5-0.9-0.7-1.8-0.7c-0.6,0-1.1,0.1-1.6,0.4c-0.5,0.3-1,0.7-1.6,1.3
v7.6h-2.2l0-16L83.7,7.6z"/>
<g>
<polygon class="st0" points="96.4,2.6 95.7,4.2 105,4.2 105.8,2.6 "/>
<polygon class="st0" points="95.7,6.1 94.9,7.7 104.3,7.7 105,6.1 "/>
<polygon class="st0" points="97.5,9.6 101.8,0.4 103.5,0.5 99.2,9.6 "/>
</g>
<g>
<path class="st0" d="M46.3,19.7c0,0.7,0.2,1.3,0.6,1.6c0.4,0.3,0.9,0.5,1.4,0.5c0.3,0,0.6,0,0.9-0.1c0.3-0.1,0.6-0.2,1-0.3l0.5,1.6
c-0.2,0.1-0.5,0.2-0.7,0.2c-0.2,0.1-0.5,0.1-0.7,0.2c-0.2,0.1-0.5,0.1-0.7,0.1c-0.3,0-0.5,0.1-0.8,0.1c-1.2,0-2.1-0.3-2.7-1
c-0.6-0.7-0.9-1.7-0.9-3V5.1h-3.5l5.6-4"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View file

@ -0,0 +1,56 @@
:root {
font-size: 14px;
}
h3 {
font-size: 1.5rem;
}
h2 {
font-size: 1.75rem;
}
.mb-5 {
margin-bottom: 1.5rem !important;
}
/* Extra large devices (large laptops and desktops, 1200px and up) */
@media only screen and (min-width: 1200px) {
:root {
font-size: 16px;
}
.mb-5 {
margin-bottom: 3rem !important;
}
}
.blue-bg {
background-color: #40a9e3;
}
.black-bg {
background-color: black;
}
.red-bg {
background-color: #d1240c;
}
.green-bg {
background-color: #5cab06;
}
h1.generic-header {
line-height: 6rem;
font-size: 7rem;
text-transform: uppercase;
}
@media only screen and (max-width: 1068px){
h1.generic-header {
font-size: 10vw;
line-height: 12vw;
}
}

View file

@ -0,0 +1,3 @@
_template: sitemap.xml
---
_model: none

View file

@ -0,0 +1,197 @@
title: How to build an OpenStack alternative: Step 1, the prototype
---
pub_date: 2020-01-11
---
author: ungleich virtualisation team
---
twitter_handle: ungleich
---
_hidden: no
---
_discoverable: yes
---
abstract:
The step by step guide for doing it yourself
---
body:
In this article we describe a first
## Find out what you need
When we say building an alternative to OpenStack, we have something
specific in our mind. This might be different from what you think
OpenStack is for. For us it is running a lot of virtual machines for
customers with a lot of storage attached. With self service and
automated payments.
All code I refer to in this article can be found on
[code.ungleich.ch](https://code.ungleich.ch/uncloud/uncloud/tree/master/uncloud/hack/hackcloud).
## Creating a network
The current setup at [Data Center
Light](/u/projects/data-center-light) relies heavily on VLANs. VLANs
however have a similar problem as IPv4 addresses: there are not that
many of them. So for our Openstack replacement we decided to go with
[VXLANs](https://en.wikipedia.org/wiki/Virtual_Extensible_LAN)
instead. We also considered
[SRV6](https://www.segment-routing.net/tutorials/2017-12-05-srv6-introduction/),
however we did not see a advantage for our use case. In fact, VXLANs
seems to be much simpler.
So before running a VM, we create a new VXLAN device and add it to a
bridge. This roughly looks as follows:
```
netid=100
dev=eth0
vxlandev=vxlan${netid}
bridgedev=br${netid}
# Create the vxlan device
ip -6 link add ${vxlandev} type vxlan \
id ${netid} \
dstport 4789 \
group ff05::${netid} \
dev ${dev} \
ttl 5
ip link set ${vxlandev} up
# Create the bridge
ip link add ${bridgedev} type bridge
ip link set ${bridgedev} up
# Add the vxlan device into the bridge
ip link set ${vxlandev} master ${bridgedev} up
```
As you can see, we are using IPv6 multicast underlying the VXLAN,
which is very practical in an IPv6 first data center.
## IP address management (IPAM)
Speaking of IPv6 first, all VMs in our new setup will again be IPv6
only and IPv4 addresses will be mapped to it via NAT64. This is very
similar to what you see at AWS, just that AWS uses
[RFC1918](https://tools.ietf.org/html/rfc1918) private IPv4 space
instead of [global unique IPv6
addresses](https://tools.ietf.org/html/rfc3587), which we do.
The advantage of using IPv6 here is that you will never ever have a
collision and that your VM is very clean: no need to think about IPv4
firewall rules, you only need to configure IPv6 settings.
In the IPv6 world, we use router advertisements as an alternative to
DHCP in the IPv4 world. This has the advantage that no state is kept
on the server.
To enable our IPAM, we add an IPv6 address to our bridge and enable
the radvd daemon:
```
ip addr add ${ip} dev ${bridgedev}
radvd -C ./radvd.conf -n -p ./radvdpid
```
A sample radvd configuration we used for testing looks like this:
```
interface br100
{
AdvSendAdvert on;
MinRtrAdvInterval 3;
MaxRtrAdvInterval 5;
AdvDefaultLifetime 3600;
prefix 2a0a:e5c1:111:888::/64 {
};
RDNSS 2a0a:e5c0::3 2a0a:e5c0::4 { AdvRDNSSLifetime 6000; };
DNSSL place7.ungleich.ch { AdvDNSSLLifetime 6000; } ;
};
```
With this, we are ready to spawn a VM!
## Create a VM
The current setup at Data Center Light uses libvirtd for creating
VMs. This is problematic, because libvirtd is not very reliabe:
sometimes it stops to answer `virsh` commands or begins to use 100%
CPU and needs to be killed and restarted regularly. We have seen this
behaviour on CentOS 5, CentOS 6, Debian 8 and Devuan 9.
So in our version, we skip libvirt and run qemu directly. It turns out
that this is actually not that hard and can be done using the
following script:
```
vmid=$1; shift
qemu=/usr/bin/qemu-system-x86_64
accel=kvm
#accel=tcg
memory=1024
cores=2
uuid=732e08c7-84f8-4d43-9571-263db4f80080
export bridge=br100
$qemu -name uc${vmid} \
-machine pc,accel=${accel} \
-m ${memory} \
-smp ${cores} \
-uuid ${uuid} \
-drive file=alpine-virt-3.11.2-x86_64.iso,media=cdrom \
-netdev tap,id=netmain,script=./ifup.sh \
-device virtio-net-pci,netdev=netmain,id=net0,mac=02:00:f0:a9:c4:4e
```
This starts a VM with a hard coded mac address using KVM
acceleration. We give the VM 2 cores and assign it an UUID so that we
can easily find it again later. For testing, we have attached an
[Alpine Linux ISO](https://alpinelinux.org/).
The interesting part is however the network part. We create a virtio
based network card and execute `ifup.sh` after qemu has been started.
The ifup.sh script looks as follows:
```
dev=$1; shift
# bridge is setup from outside
ip link set dev "$dev" master ${bridge}
ip link set dev "$dev" up
```
It basically adds the tap device to the previously created bridge.
## That's all there is
Only using above steps we spawned a test VM on a test machine that is
reachable at `2a0a:e5c1:111:888:0:f0ff:fea9:c44e`, world wide. If our
test machine is on, you should be able to reach it from anywhere in
the world.
Obviously this is not a full OpenStack replacement. However we wanted
to share the small steps that we take for creating it. And we really
like running a virtual machine hosting and wanted to show you how
much fun it can be.
## Next step
A lot of things in the above example are hard code and aren't usable
for customers directly. In the next step we will generalise some of
the above functions to get more and more nearby to provide a fully
usable OpenStack alternative.
If you are interested in this topic, you can join us on the [ungleich
chat](https://chat.ungleich.ch), the full development of our
alternative is open source.

View file

@ -0,0 +1,155 @@
title: How to build an OpenStack alternative: Step 2, secure the network
---
pub_date: 2020-01-12
---
author: ungleich virtualisation team
---
twitter_handle: ungleich
---
_hidden: no
---
_discoverable: yes!
---
abstract:
Let's secure the VM network
---
body:
In the second step of building an OpenStack alternative we have a look
on how to secure the network.
In the first step we described [how to setup a
protoype](../how-to-build-an-openstack-alternative-step-1).
Note: the name of our OpenStack alternative is
**uncloud**.
## Securing the network - of what?
Users should be able to do what they want and not limited in their
actions. On the other hand, users should be unable to disturb other
users. It's very much like in real life.
## General policy: no firewall
So for most of the user generated traffic there should be no firewall
rules in uncloud. Users should be free to configure
their own policies on the VM.
## Network types
Before applying any security mechanism, we have to think about what
kind of networks can exist in a cloud environment. We see two types of
networks:
* shared networks - more than one customer is in this network
* private networks - only one customer has access in this network
## Filtering IP address management packets
So when we share a network, we don't want one customer to be able to
assign IP addresses to other customers. Instead IP addresses should
only be assigned from the operator.
This means that we need to prevent rogue
* [Router advertisements (IPv6)](https://en.wikipedia.org/wiki/Neighbor_Discovery_Protocol)
* [DHCPv6](https://en.wikipedia.org/wiki/DHCPv6) server answers
* [DHCPv4](https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol) server answers
In our prototype we are using [nftables instead of
iptables](https://ungleich.ch/en-us/cms/blog/2018/08/18/iptables-vs-nftables/)
for firewalling, but the rules can be translated from one to another
firewall system.
To drop router advertisements, we can use the following rule:
```
icmpv6 type nd-router-advert drop
```
To drop DHCPv6 server answers we can use
```
ip6 version 6 udp sport 547 drop
```
And finally to prevent DHCPv4 server anwers, we use
```
ip version 4 udp sport 67 drop
```
Note: while uncloud does not use IPv4 or DHCPv4 to the VMs, a rogue
DHCPv4 server might still trick other VMs into assigning themself an
IPv4 address. So we also need to block this one.
## Filtering MAC and IP spoofing
A VM should not be able to spoof the
[MAC address](https://en.wikipedia.org/wiki/MAC_address) or
IP address of another machine. We can achieve this by adding a chain
specific for each VM network interface:
```
iifname tap1 ether saddr 02:00:f0:a9:c4:4e ip6 saddr 2a0a:e5c1:111:888:0:f0ff:fea9:c44e accept
```
With this we can even allow routing a network to a VM and allowing
it to use any IPv6 address in that network:
```
iifname v343a-0 ether saddr 02:00:f0:a9:c4:4f ip6 saddr 2a0a:e5c1:111:888:0:f0ff:fea9:c44f accept
iifname v343a-0 ether saddr 02:00:f0:a9:c4:4f ip6 saddr 2a0a:e5c1:111:1234::/64 accept
```
## Putting it all together
The following code is a full nftable ruleset
for securing the VM network traffic.
Note that it uses the prerouting hook so
that we can use the **ibrname** statement.
This is necessary because we don't want to
filter after routing or in a forwarding mode, but we want to already filter it
**prerouting** (hence the name).
```
flush ruleset
table bridge filter {
chain prerouting {
type filter hook prerouting priority 0;
policy accept;
ibrname br100 jump br100
}
chain br100 {
# Allow all incoming traffic from outside
iifname vxlan100 accept
# Default blocks: router advertisements, dhcpv6, dhcpv4
icmpv6 type nd-router-advert drop
ip6 version 6 udp sport 547 drop
ip version 4 udp sport 67 drop
jump br100_vmlist
drop
}
chain br100_vmlist {
# VM1
iifname tap1 ether saddr 02:00:f0:a9:c4:4e ip6 saddr 2a0a:e5c1:111:888:0:f0ff:fea9:c44e accept
# VM2
iifname v343a-0 ether saddr 02:00:f0:a9:c4:4f ip6 saddr 2a0a:e5c1:111:888:0:f0ff:fea9:c44f accept
iifname v343a-0 ether saddr 02:00:f0:a9:c4:4f ip6 saddr 2a0a:e5c1:111:1234::/64 accept
}
}
```
## Status
With this second step we create the basis for actually running VMs
that we (as an operator) don't trust. So now we have a prototype and
we have network security. We probably want to begin to automate things
in the next step.

View file

@ -0,0 +1,122 @@
title: How to build an OpenStack alternative: Step 3, Generating Mac Addresses
---
pub_date: 2020-01-13
---
author: ungleich virtualisation team
---
twitter_handle: ungleich
---
_hidden: no
---
_discoverable: yes
---
abstract:
First step to automation
---
body:
This time we describe how to begin automation in uncloud,
our OpenStack alternative.
The previous time we described
[how to secure the network](../how-to-build-an-openstack-alternative-step-2-secure-the-network/).
## Mac Addresses
Mac addresses are identifiers for network cards. Like a street number
is for a house. A virtual machine can have one or more network
interfaces. Each of these interfaces need a unique number, the mac
address.
## Choosing the prefix
We checked how [OpenNebula](https://opennebula.org/) is doing it.
They basically use the **02:00** prefix and generate mac addresses after
that. The
[QEMU mac address
prefix](https://gist.github.com/ashee/9241ab6281e6f4d1ef9b)
seems to be 52:54:00.
According to [Michael
Stapelberg](https://michael.stapelberg.ch/posts/2012-11-21-kvm_best_practices_2012/)
the **f6** prefix can be used due to the second lowest bit set to 1.
Checking with [Wikipedia](https://en.wikipedia.org/wiki/MAC_address),
this bit indeed specifies whether or not a mac address is locally or
universally administrated.
For that reason we will use **42** as our prefix, which is **1000010**
in binary and thus has the second least significant bit set to 1.
## Generating Mac addresses
Mac addresses are basically just numbers and so we treat them as
such. We need to store the index of which is the current mac address
and for the next time we create a VM, use the next mac address.
The python code to generate a new mac address looks as follows:
```
@staticmethod
def int_to_mac(number):
b = number.to_bytes(6, byteorder="big")
return ':'.join(format(s, '02x') for s in b)
def getnext(self):
if self.last:
last_number = int(self.last[0], 16)
if last_number == int('0xffffff', 16):
raise Error("Exhausted all possible mac addresses - try to free some")
next_number = last_number + 1
else:
next_number = 0
next_number_string = "{:012x}".format(next_number)
next_mac_number = self.prefix + next_number
next_mac = self.int_to_mac(next_mac_number)
```
It basically says:
* If there has been a mac address used add 1 to it and use the next
one
* Produce an error, if the whole prefix has been used
* If no mac address has been used, use the first one
* Convert the number to the standard format (aa:bb:cc:dd:ee:ff)
There is some additional logic on saving the MAC address to which we
will come back in one of the next posts.
## Using the MAC address generator
From our prototype, we modify the original `vm.sh` script to include a
call to the mac address generator as follows:
```
...
mac=$(./mac-gen.py)
...
$qemu -name "uncloud-${uuid}" \
-machine pc,accel=${accel} \
-m ${memory} \
-smp ${cores} \
-uuid ${uuid} \
-drive file=alpine-virt-3.11.2-x86_64.iso,media=cdrom \
-netdev tap,id=netmain,script=./ifup.sh,downscript=./ifdown.sh \
-device virtio-net-pci,netdev=netmain,id=net0,mac=${mac}
```
In good UNIX manner, the generator simply outputs the MAC address on
stdout to be used by any software.
## Status
While being a small and very specific tool, the mac address generator
is actually a key element of creating a virtualisation
framework. Without it, it is practically impossible to spawn a dynamic
amount of virtual machines.
With our prototype, a secured network and the mac address generator we
are not far from being able to migrate some test VMs to uncloud.

View file

@ -0,0 +1,71 @@
title: How to build an OpenStack alternative: Step 4, adding a database
---
pub_date: 2020-01-14
---
author: ungleich virtualisation team
---
twitter_handle: ungleich
---
_hidden: no
---
_discoverable: yes
---
abstract:
Data begins to accumulate
---
body:
This time we describe how to
store information in a database and why we selected etcd as the
primary database.
The previous time we described
[how to generate MAC
addresses](../how-to-build-an-openstack-alternative-step-3-automating-mac-addresses/),
a key element of uncloud.
## More Data
We now have a couple of running VMs, we want to remember which VMs
are running and also add more information. Who owns a VM? And later
also where is the VM running.
## Database
We decided to use [etcd](https://etcd.io/) as our primary database.
The main reason for it is that we don't want to add a single point of
failure into uncloud and we don't need guarantees provided by
standard SQL.
An alternative we still consider is postgresql. While it is not
inherently distributed (at all), it also
supports storing JSON and has quite a sophisticated messaging system.
## Refactoring: phasing in a database
So far we used a couple of python and shell scripts to create the base
of uncloud. Now that things become a bit more serious, we needed to
refactor our code. Shell and python scripts are cleaned up and
become python a proper python module, which we lovely call
`uncloud.hack`.
## Python, ETCD and JSON
We decided to use [python-etcd3](https://python-etcd3.readthedocs.io/)
to access etcd from the python world, as it supports the API version
3.
For the data format we decided to use JSON, as it is easy to read.
Each VM is identified by a random UUID, so we don't need to store a
counter for VMs.
## Status
At this point uncloud can create VMs and the VMs are registered
in etcd as the database. So while we don't have logic yet for
(automatic) VM migration, the information about VMs is already stored
in a distributed database.
So if one of our hosts vanishes, we can in theory already redeploy the
existing VMs.

View file

@ -0,0 +1,130 @@
title: How to build an OpenStack alternative: Step 5, adding metadata
---
pub_date: 2020-01-15
---
author: ungleich virtualisation team
---
twitter_handle: ungleich
---
_hidden: no
---
_discoverable: yes
---
abstract:
Let the VMs get information about themselves
---
body:
This time we describe how virtual machines can get information about
themselves like which ssh keys should have access to it.
The previous time we
[added a database to
uncloud](../how-to-build-an-openstack-alternative-step-4-adding-a-database/).
## Motivation
If we were to start VMs without a metadata service, all of the VMs
would be looking identical and would not be able to know, whom to
allow access to it.
To customise a VM or to make it usable, we need to tell it who has
access to it and potentially inject even more information.
## Metadata service: how others do it
Enters the metadata service. OpenNebula solves this problem quite
nicely by attaching a virtual cdrom to the VMs. That cdrom contains
only one file, `context.sh`. This file contains information about
* networking
* ssh keys
OpenStack with cloud-init on the other side uses an HTTP based
service that is found on the address `http://169.254.169.254/`.
Both schemes come with disadvantages that we don't want to replicate
in uncloud:
In the opennebula case changing metadata information while the VM is
running requires to create a new CDROM and if that one is still
mounted, the VM might not get the up-to-date information. This is a
bit of a theorethical case, as the metadata is rarely re-used after
booting.
However changing the information provided in the context.sh inside the
ISO always requires to generate a new ISO. While technical possible,
not very elegant.
The OpenStack based approach has (from our point of view) a much
bigger problem: it relies on IPv4. VMs running on uncloud primarily
run IPv6 and should function without any IPv4 stack.
The motivation for using the 169.254.0.0/16 network is clear: it works
without having an IP address management system in place.
## Solving it the smart way
So it seems like the general approach of OpenStack/cloud-init is
actually quite elegant, if it wasn't forcing IPv4.
In the IPv6 world, we always have link local addresses in the
**fe80::/10** network. Should we just replace the OpenStack approach
with IPv6?
We don't think so, it has the same argument in favor for IPv4 networks
that we have in favor for IPv6 networks.
Instead, we suggest to add a simple change to the OpenStack approach:
Use http://metadata instead of using an IP address.
## http://metadata
So how should this work and why is this better than using
http://169.254.169.254/?
Using a name, it doesn't matter whether the VM is on an IPv4 ore
IPv6 network.
Using just the hostname, not an FQDN (i.e. metadata.example.com) makes
it portable.
The name can be resolved via various methods:
* uncloud: it will be delivered by DNS
* openstack: either via DNS (like uncloud) or if there is no IPAM, it
can be statically set in /etc/hosts
In the DNS resolving case, this actually gets even more interesting,
because we can use the **DNS search path**. So while the client tries
to resolve the hostname **metadata**, the underlying resolver library
will also look for **metadata.example.com**, if example.com is in the
search path.
## uncloud implementation
In uncloud we have implemented a sample [metadata
service](https://code.ungleich.ch/uncloud/uncloud/tree/master/uncloud/metadata).
However IPAM (i.e. router advertisements) and DNS servers are not part
of uncloud and can be used from the regular system infrastructure.
In one of the next versions we plan to include helpers that allow you
to bootstrap IPAM and DNS easily.
## Status
At this point uncloud can create VMs and the VMs can get the ssh keys
that should have access from the metadata service.
With this latest add-on uncloud gets near the range of a usable
prototype. A lot of things will probably need to be refactored in the
future, but at the moment uncloud supports already:
* creating VMs (using qemu)
* securing the VM network (using nftables)
* generating unique mac addresses (uncloud python code)
* storing information in a distributed database (using pytho-etcd3 and
etcd)
* providing basic metadata inforamtion (uncloud python code)

View file

@ -0,0 +1,59 @@
title: Redesign into Zero Carbon
---
pub_date: 2020-01-26
---
author: ungleich
---
twitter_handle: ungleich
---
_hidden: no
---
_discoverable: no
---
abstract:
We need to redesign ourself into zero carbon
---
body:
## Reality check: it's been warm and it's not right
In our small mountain village in the Swiss Alps, weve been having an exceptionally warm winter. Max. 11°C in January, is still cold enough for our servers but some of the local businesses are suffering from not having enough visitors to the region, since people usually come here to enjoy skiing and other winter sports that require snow and colder weather.
![](/u/image/december2019-weather.jpg)
While one strangely warm and snowless winter is not direct evidence of climate change, we cant help but wonder what will happen if this continues every year: with such warm weather, what will happen to our mountain ecosystem and ultimately to us humans? What will happen when there is no snow left on top of the Alps?
We are in fact witnessing this change right now - the Pizol glacier in the Glarus Alps has been melting with an unprecedented speed and it is [due to disappear completely by 2030.] (https://www.swissinfo.ch/eng/reuters/climate-activists-hold-event-to-mark-vanishing-swiss-glacier/45247240) And it is just one of the many glaciers we are hopelessly watching while it melts away.
![](/u/image/world-4c-higher.jpg)
No snow on the Alps and having most parts of southern Europe turning into deserts is not a part of dystopian sci-fi scenario, but our reality that environmental scientists are forecasting with gravitas. UK Met Office researchers warn that [by 2060, the world could warm up by 4 °C](https://www.newscientist.com/article/dn19778-royal-society-paints-picture-of-a-world-4-c-warmer/) which will likely cause a serious food and water shortage for the world: animals and plants will die and so will people.
## Every fraction of degree matters, and that requires our action.
According to the environmental scientists we are living a critical time: meaning we can still change things but we don't have any time to waste before it is really too late. Last Tuesday at the World Economic Forum Davos, [Greta Thunberg read out an inspiring speech](https://youtu.be/rJ8Q_1r9L8U) which told the world that "Every fraction of degree matters." Every effort we do to reduce carbon emission matters and those of us who can, we need to do this in scale and with speed. One of the point she stressed is that richer countries need to get down to zero emission much faster than now - because we could, when we really mean to.
## The physical reality of our digital world
So what can we do? Probably most of you do some things for the environment, no doubt about that. Today what we want to talk about is reducing carbon emission from our digital world. To be specific, going zero carbon for our digital activities.
We don't assume you to be stupid, but this is often very well hidden to all of us: that everything we do online actually has carbon footprint. We just don't see it so we tend to go on without really thinking about it, but we are still responsible for everything we do - searching, clicking, downloading, uploading, transferring, streaming, really every byte counts. Because although not so apparent on the digital surface, every data exists somewhere as physical infrastructure that runs with power generated by some source, 24/7. [10 minutes of YouTube equals 1g of CO2e,](https://www.creditangel.co.uk/blog/consumption-and-carbon-footprint-of-the-internet) [30 minutes of Netflix equals 1.6 kg(!) of CO2,](https://www.news18.com/news/buzz/half-an-hour-of-netflix-and-chill-emits-the-same-amount-of-co2-as-6-km-drive-2364791.html) and the list goes on and on. You got the idea.
## How to reduce your digital CO2 emission
A very good practice you can do easily is slimming down your digital acitivity. It's also healthier for most of us to get away from the screen once in a while. Pick up a book from your local library instead of that bad movie you downloaded from torrent. (And of course walk or bike to that library if you can.) Problem solved.
No, problem not solved. Most of us do this digital thing for a living. We need to use data and some of us are actually saving the world by doing what we do. Many of us are in fact on the good side in fighting the evil (and/or) stupid side. Then what?
Then what you need to do is go renewable for your digital data. Go with renewable energy as much as you can, as fast you can.
## How do I know where my cloud is at?
True, most people don't really know or care where their data is at. We kind of know what's bad with fast fashion or disposable plastics but we didn't have to think about what kind of energy our cloud uses. In the meantime the [IT service industry grew as big as aviation industry in terms of carbon emission](https://time.com/46777/your-data-is-dirty-the-carbon-price-of-cloud-computing/) and now it takes about 2% of total global carbon emissions. So it is really about time we start to feel towards and act responsible with our cloud choices. You can start by finding out where your data physically is, and what kind of energy it uses. Most of the times it's not that hard to find out, and if it's hidden, you need to request the information to be disclosed to your provider. Where are they keeping their servers, and what is the energy source they are using? Are they running servers with coal or other fossil fuels? Or nuclear power? Or renewable energy such as water, solar or windpower?
## Zero Carbon VS. Carbon Offset
This should be an obvious point, but it's not always so obvious for most of us. Zero carbon emission from the energy source (meaning produced by 100% renewable source such as water or solarpower) is a better choice than carbon offsetting. Carbon offsetting, roughly translates into using whatever energy source available (say coal or nuclear) and paying money for funding projects for reducing the CO2 already added to the air. Carbon offsetting is a solution with its own goals and values, but it is not an answer for our critical environmental situation especially if we have zero carbon as an option. Imagine, when a glass is full, not adding any drop to it would be the sane approach if we do not want to overflow the glass.
## Where do I find the zero carbon solutions?
## What is available as Zero Carbon cloud now?
- cloud storage
- chat (mattermost and matrix)

View file

@ -0,0 +1,87 @@
title: Zero Carbon for Digital World
---
pub_date: 2020-01-29
---
author: ungleich
---
twitter_handle: ungleich
---
_hidden: no
---
_discoverable: yes
---
abstract:
We need to redesign our digital use into zero carbon
---
body:
## The temperature is rising
In our small mountain village in the Swiss Alps, weve been having an exceptionally warm winter. We had Maximum 18°C in December and 11°C in January, that is still cold enough for our servers but some of the local businesses are struggling with not having enough visitors to the region, since people usually come here to enjoy skiing and other winter sports that require snow and colder temperature.
While one strangely warm and snowless winter is not direct evidence of climate change, we cant help but wonder what will happen if this continues every year: are we in the middle of watching something that is going away for good?
![](/u/image/december2019-weather.jpg)
In the Swiss Alps one of the things we see going away every year is the glacier - the Pizol glacier in the Glarus Alps, just around the corner for us, has been melting with unprecedented speed and it is [due to disappear completely by 2030.](https://www.swissinfo.ch/eng/reuters/climate-activists-hold-event-to-mark-vanishing-swiss-glacier/45247240) And it is just one of the many glaciers we are hopelessly watching while it melts away.
![](/u/image/pizol.jpg)
When the temperature is rising and no ice is left to lock the cool air within, what will happen to our mountain ecosystem and to us people? It will certainly look different from today, and not in a good way.
No snow on the Alps and having most parts of southern Europe turning into deserts is what environmental scientists are forecasting with gravitas. UK Met Office researchers warn that [by 2060, the world could warm up by 4 °C](https://www.newscientist.com/article/dn19778-royal-society-paints-picture-of-a-world-4-c-warmer/) which will likely cause a serious food and water shortage for the world: animals and plants will face an existential threat and so will people.
![](/u/image/world-4c-higher.jpg)
## We need to keep it cool
It is important to note that we are living a critical time. Last Tuesday at the World Economic Forum Davos, the young environmental activist [Greta Thunberg told the world](https://youtu.be/rJ8Q_1r9L8U) that we have less than 8 years to stop the temperature rising from more than 1.5°C, and for that "every fraction of degree matters."
Every effort we do to reduce carbon emission matters and those of us who can, we need to do this in scale and with speed. Especially the ones residing in wealthier countries need to get down to zero emission much faster than now.
But how? We recycle our bottles and paper, we say no to plastic bags, we use more trains than planes, but is that enough to keep the world from getting hotter?
There's still something missing. When every fraction of degree matters we need to look at every aspect of our daily life with attention - especially the invisible parts.
## The physical reality of our digital world
The missing part we need to look at is the carbon emission from our digital activities: everything we do online actually has carbon footprints. We just don't see it so we tend to go on without really thinking about it, but we are still responsible for every byte we touch: searching, clicking, downloading, uploading, transferring, streaming. And our digital carbon footprint is in fact significant. Let's see some very relatable examples, [10 minutes of YouTube equals 1g of CO2e,](https://www.creditangel.co.uk/blog/consumption-and-carbon-footprint-of-the-internet) [30 minutes of Netflix equals 1.6 kg(!) of CO2,](https://www.news18.com/news/buzz/half-an-hour-of-netflix-and-chill-emits-the-same-amount-of-co2-as-6-km-drive-2364791.html).
The truth is not so apparent on the digital surface, but every data *exists* somewhere as physical infrastructure that runs 24/7 with power generated by *some* source. And it is emitting more and more CO2 into the air we are living in.
## How to reduce your digital carbon footprint
Now the question is how do we reduce, or avoid the CO2 emission from our digital use. A very good practice you can do easily is slimming down your digital activity. It's also *healthier* for most of us to get away from the screen once in a while. Pick up a book from your local library instead of that bad movie you downloaded from torrent. And of course walk or bike to that library if you can. Problem solved.
No, problem not solved. Most of us do these digital activities for a living. We need to use data and some of us are actually saving the world by doing what we do. Many of us are in fact on the good side of fighting the evil and/or stupid side. Then what?
Then what you need to do is going renewable for your digital data. Go with clean energy as much as you can, as fast you can.
## How is my digital world powered?
Maybe your digital service provider such as your chat app or photo cloud, is already run by clean energy. [But likely they are not.](http://lab.cccb.org/en/how-polluting-is-the-internet/) The picture below gives you an overview of what the energy sources are per country in Europe - and remember, Europe is on the better side of the world in terms of energy sources. But even in Europe you can see most countries still depend on non-renewable energy sources.
![](/u/image/energy-source-by-country.jpg)
We already know that fast fashion and disposable plastics are bad - that they are easy to use but destroys our environment and creates too much carbon emission in its lifecycle - and the same logic applies to our digital data. We need to acknowledge that the widely available digital services are in fact bad for the environment, say the messenger or the chat everybody around you uses, or the cloud that just comes with your device by default. As a matter of fact the IT service industry [grew as big as the aviation industry in terms of carbon emission](https://time.com/46777/your-data-is-dirty-the-carbon-price-of-cloud-computing/) and now it takes about 2% of total global carbon emissions. So it is really about time we start to act responsibly for our digital choices.
The first step for reducing your digital carbon footprint is finding out where your data physically is to know what kind of energy the infrastructure uses. If the information is hidden, you need to request your provider to disclose it. Where are they keeping their servers, and what is the energy source they are using? Are they [running servers with coal, oil or other fossil fuels?](https://www.nytimes.com/roomfordebate/2012/09/23/informations-environmental-cost/clean-it-means-clean-energy-suppliers-too) Or is your digital service run by nuclear power?
## Zero Carbon VS. Carbon Offset
When you pay attention to the energy sources of your digital services, you see that some of the service providers claim they are *green* because they do carbon offset. Then we need to ask, can carbon offset be an answer for keeping the temperature down?
The short answer is no. Imagine, when a glass is full, not adding any drop to it would be the best approach if we do not want to overflow the glass. What we need right now is *zero* carbon emission from the energy source (meaning produced by 100% renewable sources such as water or solar power) and not carbon offsetting. Carbon offsetting, roughly translates into using whatever energy source available (say fossil fuel or nuclear) and paying money for funding projects for reducing the CO2 that is already added into the air. Carbon offsetting is obviously better than not offsetting, but not emitting CO2 from the energy source is ultimately better than CO2 offsetting.
## Use small and renewable digital services
There are two ways to reduce the carbon footprint from our digital data. One is finding [the ones who are running by zero carbon already,](https://github.com/vrde/notes/tree/master/zero-carbon) and supporting them by using those instead of others. This means your digital life will be only enabled by clean energy, and you will have zero carbon emission in terms of energy used for running your services. By supporting zero carbon standard you encourage the new service providers coming into the market to start clean with renewable energy.
The second way is pushing your current service provider to change how they are running their servers, to go fully renewable. The advantage of this will be that the change will affect a bigger number of people, when really done. The disadvantage of it is that bigger companies take much more time in changing their huge infrastructure, while even more CO2 will be emitted from them into the air.
We want to stress that, for those who care and who are capable, go for the first option. It is for the same reason as the zero carbon vs. carbon offset. When there are those who already doing the right things, go with them now, instead of continuing with [those who plan to reach their goal in the coming decades.](https://www.bloomberg.com/news/articles/2019-09-20/amazon-s-emissions-bigger-than-some-rivals-trail-walmart)
## Zero Carbon to take over the status quo
So how do the small and renewable zero carbon digital services look in reality? We can take us as one of the examples.
In this small Alpine village we are located at, we are running [servers with only renewable energy.](https://datacenterlight.ch/en-us/cms/hydropower/) That is 99.9% hydropower and 0.1% solar power. Our case is a bit special because we brought our servers into old buildings that used to work as spinning and weaving factories that are built many years ago when Switzerland hosted a strong textile industry. Now the textile industry all moved out of the country looking for lower labour cost, leaving vast empty industrial buildings. Thanks to the infrastructure previously built, we directly produce the hydroelectricity a few meters away from our servers, by the water melted from the glacier on the Alps.
What we do is [we only use recycled servers,](https://ungleich.ch/en-us/cms/blog/2019/06/28/how-run-really-green-datacenter/) so we can extend their lifecycle as long as possible before they end up in the landfill. And we do not waste energy for cooling the servers: the mountain temperature is cool enough throughout the year, and the big space we have helps the servers from being overheated.
![](/u/image/zerocarbon_no.jpg)
On top of this fully renewable and recycled infrastructure runs the digital services such as cloud storage, [Zero Carbon Cloud](https://ungleich.ch/u/products/zero-carbon-cloud/) and team chat, [Zero Carbon Chat.](https://ungleich.ch/u/products/zero-carbon-chat/) These are cutting-edge applications that are developed by the fantastic open source community ([Nextcloud](https://nextcloud.com/) and [Mattermost,](https://mattermost.com/) respectively), and we make it a rule that only the services used and tested extensively by our team internally are offered to external customers. Digital services for everyday use such as Dropbox, Google Photos, iCloud, Slack, Whatsapp can be easily replaced by its Zero Carbon alternatives.
## There are more Zero Carbon to come
Our plan is releasing more zero carbon options that can replace digital services with big carbon footprints. Our next one to come is Zero Carbon Matrix which is a chat service with bridging different platforms and end-to-end encryption features, and also in the queue is Zero Carbon Code Hosting which can replace GitHub. Do you have an idea what should be our next Zero Carbon project? Share your thoughts. Talk to us via [Twitter @ungleich](https://twitter.com/ungleich)(which we plan to offer as a Zero Carbon Social soon), or you can join [our chat](https://chat.ungleich.ch) (which is also a nice test for you in using Zero Carbon Chat) or you can drop us a mail at zerocarbon@ungleich.ch.

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 KiB

View file

@ -0,0 +1,74 @@
x step 4 = database!
- image contextualisation
- dnsmasq
- metadata
- for getting keys
- user metadata
- user authentication
- otp or ldap or plain file
- for registering keys
- for creating VMs
- automating
- trigger / postgres / etcd
- building vm images!
- generate tap names matching vm??? problem, because inteerfaces are
limited in length!
[root@diamond hackcloud]# ip link add b23456789012345 type bridge
[root@diamond hackcloud]# ip link add b234567890123456 type bridge
Error: argument "b234567890123456" is wrong: "dev" not a valid ifname
[root@diamond hackcloud]#
- VMID is not uuid, but counter; using hexa; using 16**10,
gives 1099511627776 VMs
>>> (16**10)/(1000*24*365)
125515.02600182648
interface names:
x = vxlan ?
b = bridge
v = vm
=> 16 types possible
10+1 used => 4 left
2 positions for interface id? => 256 interfaces per VM
mac:
48 bits = 6 bytes
1 byte = 2hexa positions
prefix is 02:00: = 2 bytes
we have 4 bytes = 8 hexa left!!!!
embed mac suffix as ID!
full mac = 12 bytes
No vmprefix + counter -> because counter size might always be wrong
(how many interfaces? 16? 256? ... )
--------------------------------------------------------------------------------
No stale firewall entries as we regnerate, not keep the list!
table bridge filter {
chain prerouting {
type filter hook prerouting priority 0;
policy accept;
ibrname br100 jump netpublic-$version
}
chain netpublic-10 {
...
}
}
can generate new full chain, change only the jump
--------------------------------------------------------------------------------
Much later:
- rate limiting

View file

@ -0,0 +1,29 @@
_model: page-2020
---
title: Events
---
content:
The following is a list of events we provide or participate in.
## 2020
* [2020-12-04..2020-12-06: Hack4Glarus 2020 Winter Edition @ Data Center Light, Linthal](https://hack4glarus.ch/)
* [2020-06-05..2020-06-07: Hack4Glarus 2020 Summer Edition @ Data Center Light, Linthal](https://hack4glarus.ch/)
* [2020-04-25: IPv6 in der Bildung - Open Education Day @ PHBern, Bern](https://openeducationday.ch/programm-2020/ipv6-in-der-bildung/)
* [2020-02-18: 9. Glarner Innovationsapéro: Digitalisierung in der Praxis @ Linthpark, Linthal](https://www.myswitzerland.com/en-ca/experiences/events/9-glarner-innovationsapero-digitalisierung-in-der-praxis/)
## 2019
* [2019-12-12: Ungleich IPv6-only Hosting @ IPv6 Council Annual Meeting 2019, UK IPv6 Council, London](https://www.ipv6.org.uk/2019/09/06/ipv6-council-annual-meeting-2019/)
* [Ungleich IPv6-only Hosting Presentation](https://www.ipv6.org.uk/wp-content/uploads/2019/12/UKIPv6Council_meeting_2019_Ungleich_IPv6-only_Hosting.pdf)
* [2019-11-29..2019-12-01: Hack4Glarus 2019 Winter Edition @ Data Center Light, Linthal](https://hack4glarus.ch/)
* [2019-10-18..2019-10-18: RIPE79, Rotterdam](https://ripe79.ripe.net/)
* [RIPE79 Presentation](https://ripe79.ripe.net/presentations/19-How-to-Build-Maintain-and-Market-an-IPv6-only-Data-Center-RIPE79.pdf)
* [RIPE79 Recording](https://ripe79.ripe.net/archives/video/165/)
* [2019-09-03: The reasons for IPv6-only hosting @ Cloud and IPv6 Workshop, UK IPv6 Council, London](https://www.ipv6.org.uk/2019/08/08/cloud-and-ipv6-workshop/)
* [The reasons for IPv6-only hosting: Presentation](https://www.ipv6.org.uk/wp-content/uploads/2019/08/2019-IPv6-Cloud-ipv6-only-hosting.pdf)
* [2019-05-31..2019-06-02: Hack4Glarus 2019 Summer Edition @ Data Center Light, Linthal](https://hack4glarus.ch/)
* [2019-10-25: White Hat Hacking @ Digital Bridge Forum, Nur-Sultan](http://digitalbridge.kz/)
* [Profession of a White Hat Hacker (Presentation)](profession_of_a_white_hat_hacker-20191025_digitalbridge.pdf)

View file

@ -2,7 +2,11 @@ _discoverable: no
---
_hidden: no
---
title: Cloud Backup
title: Backup
---
subtitle: Your insurance in Switzerland
---
Pricing:
"VM" (IP?)

View file

@ -36,7 +36,7 @@ average 4m² surrounding area). This way we don't need to actively cool.
If you want to bring your own hardware, you can select from the
following options:
## Space
### Space
For one server we provide you with 1m² of physical shelf space. We
call this our "base unit".
@ -45,12 +45,12 @@ Your server can be 1U, 2U or even 4U high. Contact us for special sizes.
We expect your server to not create more warmth than 3000 BTU/h. If it
produces more heat, you will need to add more base units.
## Electricity
### Electricity
Your electricity usage is monitored and charged monthly. The price for
electricity is 0.2 CHF/kWh.
## Connectivity
### Connectivity
We offer 3 levels of connectivity:
@ -64,7 +64,7 @@ Bandwidth exceeding the booked tarif is charged at 2.5 CHF/Mbps.
You get a multi mode fiber cable (850nm transceivers) to your shelf.
## IP addresses
### IP addresses
* Colocation includes a /48 IPv6 network for free
* IPv4 addresses are provided using NAT64 for 9 CHF/IPv4 address/month

View file

@ -29,21 +29,8 @@ application with a good conscience and without emitting extra carbon.
content1_text:
## Development flow
The below diagram gives an overview of a typical development flow with
our Django hosting:
---
content1_image: djangohosting.svg
---
description2:
## How it works
## Components
Our Django hosting consists of 1-2 virtual machines and an optional
backup. Our customers often start with a development system
The diagram gives an overview of a typical development flow with
our Django hosting.
We strongly recommend to develop Django (like any other application)
with a version control system, even if you are just a single
@ -52,6 +39,20 @@ repository](https://code.ungleich.ch) for free
(you only need to [register an account](https://account.ungleich.ch)).
---
content1_image: djangohosting.svg
---
description2:
## Components
Depending on your stage of development, a Django hosting may contain
1 virtual machine (production), 2 virtual machines (staging +
production) and optionally a backup.
## Pricing
* Setup fee is 35 CHF

View file

@ -36,14 +36,14 @@
<!-- editor -->
<g id="node1" class="node">
<title>editor</title>
<polygon fill="none" stroke="black" points="247.5,-419 146.5,-419 146.5,-383 247.5,-383 247.5,-419"/>
<text text-anchor="middle" x="197" y="-397.3" font-family="Times,serif" font-size="14.00">Local editor</text>
<polygon fill="#40a9e3" stroke="#40a9e3" points="247.5,-419 146.5,-419 146.5,-383 247.5,-383 247.5,-419"/>
<text text-anchor="middle" x="197" y="-397.3" font-family="Times,serif" font-size="14.00" fill="#ffffff">Local editor</text>
</g>
<!-- git -->
<g id="node2" class="node">
<title>git</title>
<polygon fill="none" stroke="black" points="182,-325 16,-325 16,-289 182,-289 182,-325"/>
<text text-anchor="middle" x="99" y="-303.3" font-family="Times,serif" font-size="14.00">Local version control</text>
<polygon fill="#40a9e3" stroke="#40a9e3" points="182,-325 16,-325 16,-289 182,-289 182,-325"/>
<text text-anchor="middle" x="99" y="-303.3" font-family="Times,serif" font-size="14.00" fill="#ffffff">Local version control</text>
</g>
<!-- editor&#45;&gt;git -->
<g id="edge1" class="edge">
@ -54,8 +54,8 @@
<!-- localweb -->
<g id="node3" class="node">
<title>localweb</title>
<polygon fill="none" stroke="black" points="391.5,-325 200.5,-325 200.5,-289 391.5,-289 391.5,-325"/>
<text text-anchor="middle" x="296" y="-303.3" font-family="Times,serif" font-size="14.00">Development webserver</text>
<polygon fill="#40a9e3" stroke="#40a9e3" points="391.5,-325 200.5,-325 200.5,-289 391.5,-289 391.5,-325"/>
<text text-anchor="middle" x="296" y="-303.3" font-family="Times,serif" font-size="14.00" fill="#ffffff">Development webserver</text>
</g>
<!-- editor&#45;&gt;localweb -->
<g id="edge3" class="edge">
@ -66,9 +66,9 @@
<!-- repo -->
<g id="node5" class="node">
<title>repo</title>
<polygon fill="none" stroke="black" points="256.5,-186 125.5,-186 125.5,-148 256.5,-148 256.5,-186"/>
<text text-anchor="middle" x="191" y="-170.8" font-family="Times,serif" font-size="14.00">Code repository</text>
<text text-anchor="middle" x="191" y="-155.8" font-family="Times,serif" font-size="14.00">(f.i. git)</text>
<polygon fill="#40a9e3" stroke="#40a9e3" points="256.5,-186 125.5,-186 125.5,-148 256.5,-148 256.5,-186"/>
<text text-anchor="middle" x="191" y="-170.8" font-family="Times,serif" font-size="14.00" fill="#ffffff">Code repository</text>
<text text-anchor="middle" x="191" y="-155.8" font-family="Times,serif" font-size="14.00" fill="#ffffff">(f.i. git)</text>
</g>
<!-- git&#45;&gt;repo -->
<g id="edge2" class="edge">
@ -79,15 +79,15 @@
<!-- prodvm -->
<g id="node4" class="node">
<title>prodvm</title>
<polygon fill="none" stroke="black" points="398,-62 228,-62 228,-24 398,-24 398,-62"/>
<text text-anchor="middle" x="313" y="-46.8" font-family="Times,serif" font-size="14.00">Production Server</text>
<text text-anchor="middle" x="313" y="-31.8" font-family="Times,serif" font-size="14.00">uwsgi,nginx,postgres</text>
<polygon fill="#40a9e3" stroke="#40a9e3" points="398,-62 228,-62 228,-24 398,-24 398,-62"/>
<text text-anchor="middle" x="313" y="-46.8" font-family="Times,serif" font-size="14.00" fill="#ffffff">Production Server</text>
<text text-anchor="middle" x="313" y="-31.8" font-family="Times,serif" font-size="14.00" fill="#ffffff">uwsgi,nginx,postgres</text>
</g>
<!-- backupvm -->
<g id="node8" class="node">
<title>backupvm</title>
<polygon fill="none" stroke="black" points="699.5,-325 580.5,-325 580.5,-289 699.5,-289 699.5,-325"/>
<text text-anchor="middle" x="640" y="-303.3" font-family="Times,serif" font-size="14.00">Backup server</text>
<polygon fill="#40a9e3" stroke="#40a9e3" points="699.5,-325 580.5,-325 580.5,-289 699.5,-289 699.5,-325"/>
<text text-anchor="middle" x="640" y="-303.3" font-family="Times,serif" font-size="14.00" fill="#ffffff">Backup server</text>
</g>
<!-- prodvm&#45;&gt;backupvm -->
<g id="edge6" class="edge">
@ -106,8 +106,8 @@
<!-- stagingvm -->
<g id="node7" class="node">
<title>stagingvm</title>
<polygon fill="none" stroke="black" points="600.5,-61 475.5,-61 475.5,-25 600.5,-25 600.5,-61"/>
<text text-anchor="middle" x="538" y="-39.3" font-family="Times,serif" font-size="14.00">Staging Server</text>
<polygon fill="#40a9e3" stroke="#40a9e3" points="600.5,-61 475.5,-61 475.5,-25 600.5,-25 600.5,-61"/>
<text text-anchor="middle" x="538" y="-39.3" font-family="Times,serif" font-size="14.00" fill="#ffffff">Staging Server</text>
</g>
<!-- repo&#45;&gt;stagingvm -->
<g id="edge5" class="edge">
@ -119,8 +119,8 @@
<!-- monitoring -->
<g id="node6" class="node">
<title>monitoring</title>
<polygon fill="none" stroke="black" points="436,-185 290,-185 290,-149 436,-149 436,-185"/>
<text text-anchor="middle" x="363" y="-163.3" font-family="Times,serif" font-size="14.00">Monitoring server</text>
<polygon fill="#40a9e3" stroke="#40a9e3" points="436,-185 290,-185 290,-149 436,-149 436,-185"/>
<text text-anchor="middle" x="363" y="-163.3" font-family="Times,serif" font-size="14.00" fill="#ffffff">Monitoring server</text>
</g>
<!-- monitoring&#45;&gt;prodvm -->
<g id="edge7" class="edge">
@ -133,8 +133,8 @@
<!-- monitoringmonitor -->
<g id="node9" class="node">
<title>monitoringmonitor</title>
<polygon fill="none" stroke="black" points="562,-325 416,-325 416,-289 562,-289 562,-325"/>
<text text-anchor="middle" x="489" y="-303.3" font-family="Times,serif" font-size="14.00">Monitoring server</text>
<polygon fill="#40a9e3" stroke="#40a9e3" points="562,-325 416,-325 416,-289 562,-289 562,-325"/>
<text text-anchor="middle" x="489" y="-303.3" font-family="Times,serif" font-size="14.00" fill="#ffffff">Monitoring server</text>
</g>
<!-- monitoringmonitor&#45;&gt;monitoring -->
<g id="edge8" class="edge">

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

View file

@ -0,0 +1,143 @@
_discoverable: no
---
_hidden: no
---
title: Zero Carbon Chat
---
subtitle: backed by 100% renewable energy
---
link: https://link-to-the-real-product.ch
---
feature1_title: Hosted in Switzerland
---
feature1_text:
Zero Carbon Chat is hosted exclusively in Switzerland, offering its political stability and strict privacy laws as advantages
---
feature2_title: Full control over your privacy
---
feature2_text:
Have full control over your privacy with zero compromise. Your Zero Carbon Chat conversation stays only with you without 3rd parties access.
---
feature3_title: Thoroughly sustainable
---
feature3_text: With Zero Carbon Chat you are not using fossil fuels or unsustainable energy sources. Your chat is running on infrastructure 100% run by renewable energy.
---
content1_text:
## What is Zero Carbon Chat?
Zero Carbon Chat is a secure and sustainable alternative to your Slack or Skype, Whatsapp. Our chat offers enhanced security and full control over your privacy, and it is hosted at a datacenter run by 100% renewable energy. By using Zero Carbon Chat instead of other environmentally unsustainable chats, you and your community will help our planet stay cooler while keeping your message private.
## Whom is Zero Carbon Chat for?
Zero carbon chat is suitable for everybody who ueses chat or messanger, and wants to
make a better choice for our environmental future. It is especially
suitable for the following use case.
* If you are looking for a team chat with as little carbon footprint as possible
* If you are using Slack and want to move away from it to a secure alternative without confusing your users: Zero Carbon Chat has a very enduser-friendly user interface that offers a seamless transition from Slack in terms of UX.
* If you are looking for a team chat/group communication with an extremely easy invitation management fit for people with diverse backgrounds
* If you are looking for a team chat that is fast for joining different channels/rooms
* If you are looking for a chat with linear scaling for system overheads
* If you are dealing with sensitive data over your chat that needs to be protected against the unstable political situation
* If your team needs a communication platform that does not betray the team's values: in other words, if your team values protecting the environment.
## How can I access it?
You can access the chat easily from your browser or from the mobile app.
## Zero Carbon Chat Plans
You can start Zero Carbon Chat with below pricing plans. The cost is made of two parts, a one-time initial setup fee and the monthly plan you choose. Our team will get in touch with you as soon as we receive the order and will give you the access to the chat in 2 business days. Growing your chat after starting a plan is very easy and can be done anytime: you can schedule your upgrade with our team for free to find the ideal time for you.
---
content1_image: /u/image/carbonzero-energy-green.jpg
---
content2_text:
## Tech stack
Zero Carbon Chat is your own Mattermost instance maintained and hosted at our [hydroelectric datacenter](https://datacenterlight.ch) located in Switzerland.
At Zero Carbon Chat you will have
* Every connection to the chat secured by https
* Fully scalable chat
* Unlimited bandwidth under fair use policy
* Our Zero Carbon emission chat badge exposable on your website
* Your chat data protected by Swiss privacy laws
* Monthly or yearly credit card, or wire transfer as the payment option
* Discount for larger plans so you can be compensated more for the carbon emission you avoided
At Zero Carbon Chat you will not have
* Chat data physically hosted at servers powered by fossil fuel or other unsustainable energy sources
* Your privacy compromise from storing your data in a country where authorities have global access to your data
* Spam mails from us that use unnecessary bytes that cost all of us from our environment
* Cryptocurrency as payment option
* Unnecessary frills in our web interface which require more computing power and result in more carbon emission
---
content2_image: /u/image/zerocarbon-no.jpg
---
offer1_title: Light Chat 36 CHF/Month
---
offer1_text:
* Up to 50 users
* Fully scalable anytime (1.5 CHF/Month for 100 GB HDD)
* Application firewall included
* [Initial setup fee 30 CHF](https://ungleich.ch/product/0carbonchat-setup/)
Recommended for a small group
---
offer1_link: https://ungleich.ch/product/0carbonchat-light/
---
offer2_title: Community Chat 63 CHF/Month
---
offer2_text:
* Up to 100 users
* Fully scalable anytime (1.5 CHF/Month for 100 GB HDD)
* Application firewall included
* [Initial setup fee 30 CHF](https://ungleich.ch/product/0carbonchat-setup/)
Recommended for small to medium groups
---
offer2_link: https://ungleich.ch/product/0carbonchat-community/
---
offer3_title: Power Chat 157 CHF/Month
---
offer3_text:
* Up to 1000 users
* Fully scalable anytime (1.5 CHF/Month for 100 GB HDD)
* Application firewall included
* [Initial setup fee 30 CHF](https://ungleich.ch/product/0carbonchat-setup/)
Recommended for large groups
---
offer3_link: https://ungleich.ch/product/0carbonchat-power/
---
header:
#### generic-header ####
headers:
zero carbon chat
team chat
made clean
----
primary_color: #4da553
----
header_color: text-light
----
nav_link_color: navbar-dark

View file

@ -0,0 +1,137 @@
_discoverable: yes
---
_hidden: no
---
title: Zero Carbon Cloud
---
subtitle: backed by 100% renewable energy
---
link: https://link-to-the-real-product.ch
---
feature1_title: Fully renewable
---
feature1_text: Stop storing your data in servers run by dirty energy, we use 100% renewable power from Swiss Alps for running our computers for storing your data.
---
feature2_title: Fully sustainable
---
feature2_text: New hardware is as bad as fast fashion for the environment. We opt for fully reusing hardware and buildings to extend the lifecycle of the technology.
---
feature3_title: Fully conscious
---
feature3_text: We slim down everything as much as possible to reduce computing power and energy consumption.
---
content1_text:
## What is Zero Carbon Cloud?
In the era of rapid climate change and sea-level rise, Zero Carbon Cloud is here to provide a future-orientated data storage that does not use environmentally harmful energy sources. Zero Carbon Cloud is a safe and clean alternative to your dropbox or Google cloud. Our cloud storage service is built with sustainability to its core, with fully renewable energy and with fully recycled infrastructure.
## Whom is Zero Carbon Cloud for?
Zero Carbon Cloud is suitable for everybody who uses digital data but wants to
make a better choice for our environmental future. It is especially
suitable for the following use case.
* If you deal with 100 GB data or more per month from your phone, tablet, desktop computer,
laptop computer, servers.
* If your work requires to store or to back up data digitally.
* If your work requires to move 100 GB data or more from one device to another.
* If you need to store your data without compromising your privacy.
* If your countrys privacy laws are less reliable than Switzerland.
* If you are located at a geographic region where its political climate is less stable than your data need to be.
## How can I access it?
You can access the storage easily from your desktop, mobile phone, tablet and of course laptop.
## Zero Carbon Cloud Plans
You can start Zero Carbon Cloud with below plans. The cost is made of two parts, a one-time initial setup fee and the monthly plan you choose. Our team will get in touch with you as soon as we receive the order and will give you the access to the cloud in 1 business day. Growing your cloud after starting a plan is very easy and can be done anytime, 100 GB HDD is 1.5 CHF per month.
---
content1_image: /u/image/zerocarbon-yes.jpg
---
content2_text:
## Tech stack
Zero Carbon cloud is your own Nextcloud instance stored and run at our datacenter located in Switzerland.
At Zero Carbon Cloud you will have
* Fully scalable storage and backup
* Your offsite backup for your own NAS
* Unlimited bandwidth under fair use policy
* Our zero carbon emission cloud badge exposable on your website
* Safe data storage protected by Swiss privacy laws
* Monthly or yearly credit card payment option, or wire transfer payment option
* Discount for larger plans so you can be compensated more for the carbon emission you saved
At Zero Carbon Cloud you will not have
* Storage run by fossil fuel and other unsustainable energy sources
* Spam mails from us that use unnecessary bytes that cost all of us from our environment
* Cryptocurrency payment option
* Unnecessary frills in our web interface which again increase the
computing power and result in more carbon emission
---
content2_image: /u/image/zerocarbon-no.jpg
---
offer1_title: 100 GB @ 23CHF/month
---
offer1_text:
* **One free IPv6 VPN** included for increased security
* Datacenter location: Glarus, Switzerland
* Enhanced security by limiting access to only your devices
* [1 time initial setup fee 35 CHF](https://ungleich.ch/product/0carboncloud-setup/)
Recommended for your private use or for a smaller project
---
offer1_link: https://ungleich.ch/product/0carboncloud-100GB/
---
offer2_title: 1 TB @ 36.5CHF/month
---
offer2_text:
* **Two free IPv6 VPNs** included for increased security
* Datacenter location: Glarus, Switzerland
* Enhanced security by limiting access to only your devices
* [1 time initial setup fee 35 CHF](https://ungleich.ch/product/0carboncloud-setup/)
Recommended for small to medium organisations
---
offer2_link: https://ungleich.ch/product/0carboncloud-1TB/
---
offer3_title: 50 TB @ 540 CHF/month
---
offer3_text:
* **Ten free IPv6 VPNs** included for increased security
* Datacenter location: Glarus, Switzerland
* Enhanced security by limiting access to only your devices
* [1 time initial setup fee 35 CHF](https://ungleich.ch/product/0carboncloud-setup/)
* **30% large scale discount** applied
Recommended for medium to large organisations
---
offer3_link: https://ungleich.ch/product/0carboncloud-50TB/
---
header:
#### generic-header ####
headers:
don't offset,
do zero carbon.
zero carbon cloud
----
primary_color: #40a9e3
----
header_color: text-light
----
nav_link_color: navbar-dark

View file

@ -0,0 +1,22 @@
title: IPv6.Chat
---
subtitle: Let's talk about IPv6
---
content:
## IPv6 chat
IPv6 deployment and usage is growing and with that the need to find
answers to common IPv6 questions.
We have created a chat room dedicated to IPv6 so that anyone can
exchange their ideas about IPv6.
You can join the chat via
* [IPv6.chat](https://IPv6.chat) (via Mattermost)
* #ipv6:ungleich.ch (via Matrix)
Note: there is also an #ipv6 channel on Freenode. We are currently
trying to figure out whether we can bridge IPv6.chat into the IRC room
to combine them.

View file

@ -0,0 +1,16 @@
title: Open Chat
---
subtitle: Open Source requires Open Communication
---
content:
You can chat with us either via Mattermost on
[chat.ungleich.ch](https://chat.ungleich.ch) or
Matrix on [matrix.ungleich.ch](https://matrix.ungleich.ch).
For matrix you can find our public channels on **+public:ungleich.ch**.
To foster IPv6 deployement, we created [IPv6.chat](../ipv6-chat),
which is also reachable on both chat systems.
And some of our channels are also available on IRC, you can find them
on the [list of bridged channels](https://redmine.ungleich.ch/projects/open-infrastructure/wiki/CHATting_with_ungleich).

View file

@ -0,0 +1,84 @@
title: Open Source
---
subtitle: Open Source literally created ungleich
---
content:
## History of Open Source at ungleich
Open Source at ungleich is deeply rooted. It is actually Open Source
that started ungleich in 2013: You might now that
[Nico](https://www.nico.schottelius.org), the founder of ungleich,
is one of the two
original authors of [cdist](https://cdi.st), an Open Source
configuration management system (Steven Armstrong being the other
crazy person).
In 2013 a company from France requested commercial support for
cdist and soon after other Swiss companies were asking for Open Source
Software consultancy. This is how ungleich was originally born.
Whenever possible, we ask our customers to make the code that we
create for them also Open Source and some of our customers very much
welcome this approach.
In 2017 we started the [Data Center Light
project](../data-center-light), which turns old buildings (like
factory halls) into data centers.
We realised that many problems that we solve are repeating
infrastructure problems.
For that reason we created the [Open
Infrastructure project](https://redmine.ungleich.ch/projects/open-infrastructure).
in 2018 to open source our infrastructure and have others profit from
our experiences. Also in 2017 we released an
[Open Source Crowdfunding Platform together with
200ok](https://200ok.ch/posts/joint-release-of-swiss-crowdfunder.html).
We also released the
[ungleich-tools](https://code.ungleich.ch/ungleich-public/ungleich-tools)
that we use to manage or support the infrastructure. Or you can find
checkout the [backup tool
ccollect](https://www.nico.schottelius.org/software/ccollect/) that we
maintain. Or if you are ever in the need to track your time,
we have [time tracking for
geeks](https://www.nico.schottelius.org/software/ctt/).
## Open Source at ungleich today
Almost all of our products are based on Open Source Software, which is
why we contribute back to projects that we use.
While we still have [our github
account](https://github.com/orgs/ungleich/), most of our public code
can be found on
[code.ungleich.ch](https://code.ungleich.ch/ungleich-public/).
We also think that **Open Communication** is important and for that
reason we allow [free access to our company chat](../open-chat) via
Mattermost and Matrix.
We started the [Digital Glarus project](../digital-glarus) to
support the local community and just recently opened the [Hacking
Hotel](../hacking-hotel) in Diesbach to welcome (FOSS) hackers from
all around the world.
And twice per year we welcome hackers to our (strongly Open Source
driven) hackathon [Hack4Glarus](https://hack4glarus.ch).
Even this website is fully Open Source and if you don't like something
on it, we look forward to a merge request against the
[ungleich-staticcms](https://code.ungleich.ch/ungleich-public/ungleich-staticcms)
repository.
## SEE ALSO
* [ccollect](https://www.nico.schottelius.org/software/ccollect/)
* [ctt](https://www.nico.schottelius.org/software/ctt/)
* [Open Chat](../open-chat)
* [Open Infrastructure](https://redmine.ungleich.ch/projects/open-infrastructure)
* [Public ungleich git repositories](https://code.ungleich.ch/ungleich-public/)
* [uncloud repository](https://code.ungleich.ch/uncloud/uncloud)
* [ungleich-staticcms](https://code.ungleich.ch/ungleich-public/ungleich-staticcms)
* [ungleich-tools](https://code.ungleich.ch/ungleich-public/ungleich-tools)

View file

@ -0,0 +1,26 @@
[block]
name = generic-header
[fields.headers]
label = headers
type = strings
[fields.primary_color]
name = Landing Page Primary Color
label = primary_color
type = string
[fields.header_color]
name = Header Color
label = header_color
type = select
choices = text-light, text-dark
choice_labels = light, dark
default = text-light
[fields.nav_link_color]
name = Navigation Link Color
type = select
choices = navbar-light, navbar-dark
choice_labels = dark, light
default = dark

View file

@ -12,6 +12,10 @@ size = large
label = Subtitle
type = string
[fields.header]
type = flow
flow_blocks = generic-header
[fields.description1]
label = Description 1
type = markdown
@ -51,7 +55,7 @@ type = markdown
[fields.content1_text]
label = Content1 Text
type = text
type = markdown
[fields.content1_image]
label = Content 1 Image
@ -59,7 +63,7 @@ type = url
[fields.content2_text]
label = Content 2 Text
type = text
type = markdown
[fields.content2_image]
label = Content 2 Image
@ -71,7 +75,7 @@ type = string
[fields.offer1_text]
label = Offer 1 Text
type = text
type = markdown
[fields.offer1_link]
label = Offer 1 Link
@ -83,7 +87,7 @@ type = string
[fields.offer2_text]
label = Offer 2 Text
type = text
type = markdown
[fields.offer2_link]
label = Offer 2 Link
@ -95,7 +99,7 @@ type = string
[fields.offer3_text]
label = Offer 3 Text
type = text
type = markdown
[fields.offer3_link]
label = Offer 3 Link

View file

@ -0,0 +1,7 @@
<div class="jumbotron jumbotron-fluid" style="background-color: {{this.primary_color}};">
<div class="container-fluid">
{% for h in this.headers %}
<h1 class="display-1 generic-header {{this.header_color}}" style="font-weight: bolder;">{{h}}</h1>
{% endfor %}
</div>
</div>

View file

@ -5,12 +5,13 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>{% block title %}Welcome to ungleich.ch{% endblock %}</title>
<title>ungleich.ch - {% block title %}Welcome!{% endblock %}</title>
<!-- Bootstrap + helpers2 -->
<link rel="stylesheet"
href="/u/static/bootstrap-4.4.1-dist/css/bootstrap.min.css">
<link rel="shortcut icon" href="/u/static/images/favicon.ico"/>
<link rel="stylesheet" href="/u/static/generic-header.css"/>
<!-- Google analytics -->
<script>
@ -26,8 +27,21 @@
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="https://ungleich.ch">ungleich</a>
{% if this.header %}
{% set nav_style = 'background-color:' + this.header.blocks[0].primary_color + ';' %}
{% set nav_classes = this.header.blocks[0].nav_link_color %}
{% else %}
{% set nav_classes = 'navbar-light bg-light' %}
{% endif %}
<nav class="navbar navbar-expand-lg {{ nav_classes }}" style="{{ nav_style }}">
<a class="navbar-brand" href="https://ungleich.ch">
{% if 'navbar-dark' in nav_classes %}
<img src="/u/image/ungleich-logo-white.svg" width="100px" alt="ungleich" style='padding-top: 0.5rem; padding-bottom: 0.8rem;'>
{% else %}
<img src="/u/image/ungleich-logo-black.svg" width="100px" alt="ungleich" style='padding-top: 0.5rem; padding-bottom: 0.8rem;'>
{% endif %}
</a>
<button class="navbar-toggler" type="button"
data-toggle="collapse"
data-target="#navbarSupportedContent"
@ -39,22 +53,25 @@
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="/blog/">Old Blog<a/>
<a class="nav-link" href="/blog/">OLD BLOG<a/>
</li>
<li class="nav-item active">
<a class="nav-link" href="/u/blog/">New Blog<a/>
<a class="nav-link" href="/u/blog/">NEW BLOG<a/>
</li>
<li class="nav-item active">
<a class="nav-link" href="https://chat.ungleich.ch/">Chat<a/>
<a class="nav-link" href="https://chat.ungleich.ch/">CHAT<a/>
</li>
<li class="nav-item">
<a class="nav-link" href="/u/products/">Products</a>
<a class="nav-link" href="/u/products/">PRODUCTS</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/u/projects/">Projects</a>
<a class="nav-link" href="/u/projects/">PROJECTS</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/u/deals/">Deals</a>
<a class="nav-link" href="/u/deals/">DEALS</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/u/events/">EVENTS</a>
</li>
</ul>
<form class="form-inline my-2 my-lg-0"
@ -62,17 +79,12 @@
<input class="form-control mr-sm-2" type="search"
placeholder="Search" name="query" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
<a class="nav-link" href="/u/">
<button type="button" class="btn btn-info"
style="margin-left: 8px;">
BETA Website
</button>
</a>
</form>
</div>
</nav>
{% if this.header %}
{{ this.header.blocks[0] }}
{% else %}
<div class="position-relative overflow-hidden p-3 p-md-5 m-md-3 text-center bg-light">
<div class="col-md-5 p-lg-5 mx-auto my-5">
<h1 class="display-4 font-weight-normal">{{ self.title() }}
@ -83,6 +95,7 @@
<div class="product-device shadow-sm d-none d-md-block"></div>
<div class="product-device product-device-2 shadow-sm d-none d-md-block"></div>
</div>
{% endif %}
{% block content %}{% endblock %}

7
templates/sitemap.xml Normal file
View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
{%- for page in [site.root] if page != this recursive %}
<url><loc>{{ page|url(external=true) }}</loc></url>
{{- loop(page.children) }}
{%- endfor %}
</urlset>