diff --git a/docs/CNAME b/docs/CNAME new file mode 100644 index 0000000..eacc754 --- /dev/null +++ b/docs/CNAME @@ -0,0 +1 @@ +gokrazy.org diff --git a/docs/favicon.ico b/docs/favicon.ico new file mode 100644 index 0000000..32c597c Binary files /dev/null and b/docs/favicon.ico differ diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..d28822b --- /dev/null +++ b/docs/index.html @@ -0,0 +1,132 @@ + + + + + + +gokrazy - a pure-Go userland for your Raspberry Pi 3 appliances + + + + + + + +
+

gokrazy

+
+ + + +
+ +

gokrazy is a pure-Go userland for your Raspberry Pi 3 appliances

+

+ For a long time, we were unhappy with having to care about security + issues and Linux distribution maintenance on our various Raspberry Pis. +

+

+ Then, we had a crazy idea: what if we got rid of memory-unsafe + languages and all software we don’t strictly need? +

+

+ Turns out this is feasible. gokrazy is the result. +

+
+ +
+
+

Your app(s) + only 4 moving parts

+
    +
  1. the Linux kernel
  2. +
  3. the Raspberry Pi firmware files
  4. +
  5. the Go compiler and standard library
  6. +
  7. the gokrazy userland
  8. +
+

+ All are updated using the same command. +

+ +

Web status interface

+

+ On a regular Linux distribution, we’d largely use systemctl’s start, + stop, restart and status verbs to manage our applications. gokrazy + comes with a convenient web interface for + seeing process status and stopping/restarting processes. +

+ +

Debugging

+

+ Sometimes, an interactive busybox session or a quick + tcpdump run are invaluable. breakglass allows + you to temporarily enable SSH/SCP-based authenticated remote code + execution: scp your statically compiled binary, then run it + interactively via ssh. +

+
+ +
+

Constraints

+

+ Due to no C runtime environment being present, your code must compile + with the environment variable CGO_ENABLED=0. To + cross-compile for the Raspberry Pi 3, use GOARCH=arm64. + If your program still builds, you’re good to go! +

+ +

Network updates

+

+ After building a new gokrazy image on your computer, you can easily + update an existing gokrazy installation in-place thanks to the A/B + partitioning scheme we use. Just specify the -update + flag when building your new image. +

+ +

Minimal state and configuration

+

+ A tiny amount of configuration is built into the images (e.g. + hostname, password, serial console behavior). In general, we prefer + auto-configuration (e.g. DHCP) over config files. If you need more + configurability, you may need to replace some of our programs. +

+
+
+ + + +
+ + + + + diff --git a/docs/jumbotron-narrow.css b/docs/jumbotron-narrow.css new file mode 100644 index 0000000..fb7c49a --- /dev/null +++ b/docs/jumbotron-narrow.css @@ -0,0 +1,79 @@ +/* Space out content a bit */ +body { + padding-top: 20px; + padding-bottom: 20px; +} + +/* Everything but the jumbotron gets side spacing for mobile first views */ +.header, +.marketing, +.footer { + padding-right: 15px; + padding-left: 15px; +} + +/* Custom page header */ +.header { + border-bottom: 1px solid #e5e5e5; +} +/* Make the masthead heading the same height as the navigation */ +.header h3 { + padding-bottom: 19px; + margin-top: 0; + margin-bottom: 0; + line-height: 40px; +} + +/* Custom page footer */ +.footer { + padding-top: 19px; + color: #777; + border-top: 1px solid #e5e5e5; +} + +/* Customize container */ +@media (min-width: 768px) { + .container { + max-width: 730px; + } +} +.container-narrow > hr { + margin: 30px 0; +} + +/* Main marketing message and sign up button */ +.jumbotron { + text-align: center; + border-bottom: 1px solid #e5e5e5; +} +.jumbotron .btn { + padding: 14px 24px; + font-size: 21px; +} + +/* Supporting marketing content */ +.marketing { + margin: 40px 0; +} +.marketing p + h4 { + margin-top: 28px; +} + +/* Responsive: Portrait tablets and up */ +@media screen and (min-width: 768px) { + /* Remove the padding we set earlier */ + .header, + .marketing, + .footer { + padding-right: 0; + padding-left: 0; + } + /* Space out the masthead */ + .header { + margin-bottom: 30px; + } + /* Remove the bottom border on the jumbotron for visual effect */ + .jumbotron { + border-bottom: 0; + } +} diff --git a/docs/jumbotron-narrow.min.css b/docs/jumbotron-narrow.min.css new file mode 100644 index 0000000..0c5a883 --- /dev/null +++ b/docs/jumbotron-narrow.min.css @@ -0,0 +1 @@ +body{padding-top:20px;padding-bottom:20px}.header,.marketing,.footer{padding-right:15px;padding-left:15px}.header{border-bottom:1px solid #e5e5e5}.header h3{padding-bottom:19px;margin-top:0;margin-bottom:0;line-height:40px}.footer{padding-top:19px;color:#777;border-top:1px solid #e5e5e5}@media(min-width:768px){.container{max-width:730px}}.container-narrow>hr{margin:30px 0}.jumbotron{text-align:center;border-bottom:1px solid #e5e5e5}.jumbotron .btn{padding:14px 24px;font-size:21px}.marketing{margin:40px 0}.marketing p+h4{margin-top:28px}@media screen and (min-width:768px){.header,.marketing,.footer{padding-right:0;padding-left:0}.header{margin-bottom:30px}.jumbotron{border-bottom:0}} \ No newline at end of file diff --git a/docs/logo.png b/docs/logo.png new file mode 100644 index 0000000..05b5286 Binary files /dev/null and b/docs/logo.png differ diff --git a/docs/logo.svg b/docs/logo.svg new file mode 100644 index 0000000..927ce51 --- /dev/null +++ b/docs/logo.svg @@ -0,0 +1,663 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/modules/index.html b/docs/modules/index.html new file mode 100644 index 0000000..42e7aa1 --- /dev/null +++ b/docs/modules/index.html @@ -0,0 +1,80 @@ + + + + + +using Go modules + + + + + + + +
+

gokrazy

+
+ + +
+
+

Using Go modules

+ +

pull in repositories from your GOPATH

+

+ By default, Go modules will not look at $GOPATH/src, + i.e. all packages passed to gokr-packer will be downloaded. If you + had unpublished changes or packages in your $GOPATH, + you can use the following steps to declare a Go module and pull it + into the build: +

+
IMPORTPATH=github.com/stapelberg/gibot-i3
+(cd $(go env GOPATH)/src/${IMPORTPATH?} && GO111MODULE=on go mod init ${IMPORTPATH?})
+go mod edit -require ${IMPORTPATH?}@v0.0.0
+go mod edit -replace ${IMPORTPATH?}=$(go env GOPATH)/src/${IMPORTPATH?}
+
+ +

pull in local repositories

+

+ Please see https://github.com/golang/go/wiki/Modules#when-should-i-use-the-replace-directive. +

+ +
+
+ + +
+ + + + + diff --git a/docs/overview.png b/docs/overview.png new file mode 100644 index 0000000..6e6f2bc Binary files /dev/null and b/docs/overview.png differ diff --git a/docs/platforms.html b/docs/platforms.html new file mode 100644 index 0000000..f057b1d --- /dev/null +++ b/docs/platforms.html @@ -0,0 +1 @@ +https://gokrazy.org/platforms/ \ No newline at end of file diff --git a/docs/platforms/index.html b/docs/platforms/index.html new file mode 100644 index 0000000..a90f102 --- /dev/null +++ b/docs/platforms/index.html @@ -0,0 +1,135 @@ + + + + + +gokrazy platforms + + + + + + + +
+

gokrazy

+
+ + +
+
+

Supported platforms

+

+ bold appliances are tested in the CI setup on real + hardware and gate new kernel and firmware versions, and hence can be + considered supported. +

+ +

+ Regular appliances are supported in a best-effort way, i.e. they + might be temporarily broken at HEAD. +

+ +

+ The leading github.com in front of package import paths has been omitted for space reasons. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TargetHardwareGOARCHKernel packageFirmware packageAppliances
apu2c4apu2c4amd64rtr7/kernelrtr7/kernel + gokrazy/bakery/cmd/bake
+ rtr7/router7 +
x86-64qemuamd64rtr7/kernelrtr7/kernelgokrazy/bakery/cmd/bake
rpi3braspi3barm64gokrazy/kernelgokrazy/firmware + gokrazy/bakery/cmd/bake
+ stapelberg/avr-x1100w
+ stapelberg/dornröschen
+ stapelberg/hmgo
+ stapelberg/scan2drive +
rpi3b+raspi3b+arm64gokrazy/kernelgokrazy/firmwaregokrazy/bakery/cmd/bake
+ +
+
+ + +
+ + + + + diff --git a/docs/prototyping.html b/docs/prototyping.html new file mode 100644 index 0000000..68aa245 --- /dev/null +++ b/docs/prototyping.html @@ -0,0 +1 @@ +https://gokrazy.org/prototyping/ \ No newline at end of file diff --git a/docs/prototyping/index.html b/docs/prototyping/index.html new file mode 100644 index 0000000..7268b60 --- /dev/null +++ b/docs/prototyping/index.html @@ -0,0 +1,256 @@ + + + + + +gokrazy prototyping + + + + + + + +
+

gokrazy

+
+ + +
+
+

Prototyping

+

+ To realize the full benefits of gokrazy, you need to use only + software written in Go. If there is no Go software for what you want + to do, creating that piece of software can pose a seemingly + unsurmountable hurdle. To make some quick progress and figure out if + your idea can be implemented, it might make sense to temporarily use + existing software before starting your own implementation. +

+ +

+ This article shows a couple of techniques for getting non-Go + software to work on gokrazy, in increasing order of complexity. +

+ +

+ Note that software which is manually installed like shown + here will not be automatically updated by gokrazy + and hence poses a security risk. Use these techniques only for + prototyping. +

+ +

Go software not written for gokrazy: node-exporter

+

+ The Prometheus node-exporter doesn’t use cgo and needs no + command-line parameters, configuration files or other assets can be + added to the gokr-packer command line. +

+ +

Go software not written for gokrazy: Grafana

+

+ It would not suffice to add Grafana to your gokr-packer + command, as the resulting Grafana binary requires assets, supports + plugins, keeps state, etc. +

+ +

+ Hence, you need to manually install Grafana into a directory + underneath /perm. A convenient way to do that is to + use breakglass + to download the “Standalone Linux Binaries” release from + https://grafana.com/grafana/download?platform=arm. Note + that I am serving the file from my computer because my busybox + version supports neither HTTPS nor DNS. +

+ +
+/tmp/breakglass531810560 # wget http://10.0.0.76:4080/grafana-5.3.2.linux-arm64.tar.gz
+/tmp/breakglass531810560 # tar xf grafana-5.3.2.linux-arm64.tar.gz
+ +

+ We cannot start Grafana yet, as its binary is dynamically + linked. One way to fix this is to place the sources which correspond + to the release you just unpacked (e.g. from + https://github.com/grafana/grafana/tree/v5.3.2) + in your $GOPATH and recompile the binaries: +

+ +
GOARCH=arm64 CGO_ENABLED=1 CC=aarch64-linux-gnu-gcc go install \
+	    -ldflags "-linkmode external -extldflags -static" \
+	    github.com/grafana/grafana/pkg/cmd/...
+ +

+ Note that it is usually easier to set the environment + variable CGO_ENABLED=0 to get a statically linked + binary, but Grafana uses sqlite3, which is written in C, so we + resort to the -ldflags variant. +

+ +

+ At this point, we can start Grafana from breakglass: +

+ +
+/tmp/breakglass531810560 # cd grafana-5.3.2
+/tmp/breakglass531810560/grafana-5.3.2 # wget http://10.0.0.76:4080/grafana-server
+/tmp/breakglass531810560/grafana-5.3.2 # install -m 755 grafana-server bin/ && rm grafana-server
+/tmp/breakglass531810560/grafana-5.3.2 # ./bin/grafana-server
+INFO[10-30|19:27:51] Starting Grafana                         logger=server version=5.0.0 commit=NA compiled=2018-10-30T19:27:51+0100
+…
+ + +

+ To have gokrazy start Grafana, we can use a Go package like this: +

+ +
+package main
+
+import (
+  "log"
+  "syscall"
+)
+
+func main() {
+  const bin = "/perm/grafana/bin/grafana-server"
+  if err := syscall.Exec(bin, []string{bin, "-homepath=/perm/grafana"}, nil); err != nil {
+    log.Fatal(err)
+  }
+}
+
+ +

C software: WireGuard

+ +

+ WireGuard is a modern VPN tunnel, which consists of a Linux kernel + module and a configuration + tool. See rtr7/kernel@c7afbc1f + for how the kernel module was added to the router7 kernel. +

+ +

+ The configuration tool can be statically cross-compiled. We can run + Debian in a Docker container to not mess with our host system: +

+ +
+% mkdir /tmp/wg
+% cd /tmp/wg
+% docker run -t -i debian
+root@d1728eaaa6e1:/# dpkg --add-architecture arm64
+root@d1728eaaa6e1:/# apt update
+root@d1728eaaa6e1:/# apt install libmnl-dev:arm64 libelf-dev:arm64 linux-headers-amd64 crossbuild-essential-arm64 pkg-config wget
+root@d1728eaaa6e1:/# wget https://git.zx2c4.com/WireGuard/snapshot/WireGuard-0.0.20181018.tar.xz
+root@d1728eaaa6e1:/# tar xf WireGuard-0.0.20181018.tar.xz
+root@d1728eaaa6e1:/# cd WireGuard-0.0.20181018/src/tools
+root@d1728eaaa6e1:/# make CC=aarch64-linux-gnu-gcc LDFLAGS=-static
+root@d1728eaaa6e1:/# exit
+% docker cp -L d1728eaaa6e1:/WireGuard-0.0.20181018/src/tools/wg .
+ +

+ Now we can copy and run the wg binary via breakglass: +

+ +
+/tmp/breakglass531810560 # wget http://10.0.0.76:4080/wg
+/tmp/breakglass531810560 # chmod +x wg
+/tmp/breakglass531810560 # ./wg --help
+Usage: ./wg <cmd> [<args>]
+…
+ +

C software: tc

+

+ Linux’s Traffic Control system (used e.g. for traffic shaping) is + configured with the tc tool. +

+ +

+ tc is a special case in that it requires to be + dynamically linked. The different queueing disciplines are + implemented as plugins, and statically linking tc + results in a binary which starts but won’t be able to display or + change queueing disciplines. +

+ +

+ Because gokrazy doesn’t include a C runtime environment, we’ll need + to copy not only the tc binary, but also the dynamic + loader and all required shared libraries. We can run Debian in a + Docker container to not mess with our host system: +

+ +
+% mkdir /tmp/iproute
+% cd /tmp/iproute
+% docker run -t -i debian
+root@6e530a973d45:/# dpkg --add-architecture arm64
+root@6e530a973d45:/# apt update
+root@6e530a973d45:/# apt install iproute2:arm64 qemu-user-static
+root@6e530a973d45:/# LD_TRACE_LOADED_OBJECTS=1 qemu-aarch64-static /sbin/tc
+	libelf.so.1 => /usr/lib/aarch64-linux-gnu/libelf.so.1 (0x00000040008a6000)
+	libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x00000040008cb000)
+	libdl.so.2 => /lib/aarch64-linux-gnu/libdl.so.2 (0x0000004000976000)
+	libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000004000989000)
+	/lib/ld-linux-aarch64.so.1 (0x0000004000870000)
+	libz.so.1 => /lib/aarch64-linux-gnu/libz.so.1 (0x0000004000ad3000)
+root@6e530a973d45:/# exit
+% docker cp -L 6e530a973d45:/sbin/tc .
+% docker cp -L 6e530a973d45:/lib/ld-linux-aarch64.so.1 .
+% docker cp -L 6e530a973d45:/usr/lib/aarch64-linux-gnu/libelf.so.1 .
+% docker cp -L 6e530a973d45:/lib/aarch64-linux-gnu/libm.so.6 .
+% docker cp -L 6e530a973d45:/lib/aarch64-linux-gnu/libdl.so.2 .
+% docker cp -L 6e530a973d45:/lib/aarch64-linux-gnu/libc.so.6 .
+% docker cp -L 6e530a973d45:/lib/aarch64-linux-gnu/libz.so.1 .
+ +

+ Now we can copy the contents of the temporary directory to + e.g. /perm/tc and run the tc command in + breakglass: +

+ +
+/tmp/breakglass531810560 # wget -O- http://10.0.0.76:4080/tc.tar | tar xf -
+/tmp/breakglass531810560 # LD_LIBRARY_PATH=$PWD ./ld-linux-aarch64.so.1 ./tc
+Usage: tc [ OPTIONS ] OBJECT { COMMAND | help }
+…
+ +
+
+ + +
+ + + + + diff --git a/docs/quickstart.html b/docs/quickstart.html new file mode 100644 index 0000000..8ef6dd4 --- /dev/null +++ b/docs/quickstart.html @@ -0,0 +1 @@ +https://gokrazy.org/quickstart/ \ No newline at end of file diff --git a/docs/quickstart/index.html b/docs/quickstart/index.html new file mode 100644 index 0000000..35ae262 --- /dev/null +++ b/docs/quickstart/index.html @@ -0,0 +1,119 @@ + + + + + +gokrazy quickstart + + + + + + + +
+

gokrazy

+
+ + +
+
+

Get a Raspberry Pi 3 (no other model)

+

+ Currently, the Raspberry Pi 3 is the only + model supported. Many people assume the Raspberry Pi Zero W + could be used as well. Unfortunately, it uses the older + BCM2835 SoC, which is not arm64, so gokrazy won’t run on + it. See + also stapelberg’s + reddit comment about supported hardware. +

+ +

Install Go

+

+ If you don’t already have Go installed, install the latest Go version. +

+ +

Install the gokrazy packer

+
INSTANCE=gokrazy/hello; mkdir -p ~/${INSTANCE?} && cd ~/${INSTANCE?} && echo module ${INSTANCE?} > go.mod
+go get -u github.com/gokrazy/tools/cmd/gokr-packer
+ +

Overwrite an SD card with gokrazy

+

+ Plug an SD card into your card reader and locate its device node by checking dmesg | tail. In this example, we’ll assume the SD card is accessible as /dev/sdb. +

+

+ To overwrite the entire SD card /dev/sdb with a gokrazy installation running a hello world program, use: +

+
cd ~/gokrazy/hello
+gokr-packer -overwrite=/dev/sdb github.com/gokrazy/hello github.com/gokrazy/serial-busybox
+

+ The gokr-packer command above will result in log output like this: +

+
2017/03/01 20:59:55 packer.go:85: installing [github.com/gokrazy/hello]
+2017/03/01 20:59:56 packer.go:131: partitioning /dev/sdb
+2017/03/01 20:59:56 parttable.go:40: device holds 15931539456 bytes
+2017/03/01 20:59:56 packer.go:139: waiting for /dev/sdb1 to appear
+If your applications need to store persistent data, create a file system using e.g.:
+
+	mkfs.ext4 /dev/sdb4
+
+To boot gokrazy, plug the SD card into a Raspberry Pi 3 (no other model supported)
+
+To interact with the device, gokrazy provides a web interface reachable at:
+
+	http://gokrazy:<automatically-generated-random-password>@gokrazy/
+
+There will be not be any other output (no HDMI, no serial console, etc.)
+

+ After booting from this SD card, your Raspberry Pi 3 will: +

    +
  • obtain an IP address for hostname “gokrazy” via DHCP (IPv4) and SLAAC (IPv6)
  • +
  • synchronize the clock using NTP
  • +
  • expose a password-authenticated web interface on private IP addresses
    + (the default password can be recovered from ~/.config/gokrazy/http-password.txt)
  • +
  • supervise all installed programs (only the hello world program in this example)
  • +
+ The only way for you to interact with the device is via the + web interface (unless the installed programs provide other + ways). There will be no HDMI output, no serial console, etc. +

+
+
+ + +
+ + + + + diff --git a/docs/robots.txt b/docs/robots.txt new file mode 100644 index 0000000..4f9540b --- /dev/null +++ b/docs/robots.txt @@ -0,0 +1 @@ +User-agent: * \ No newline at end of file diff --git a/docs/showcase.html b/docs/showcase.html new file mode 100644 index 0000000..efde410 --- /dev/null +++ b/docs/showcase.html @@ -0,0 +1 @@ +https://gokrazy.org/showcase/ \ No newline at end of file diff --git a/docs/showcase/index.html b/docs/showcase/index.html new file mode 100644 index 0000000..b082ed5 --- /dev/null +++ b/docs/showcase/index.html @@ -0,0 +1,139 @@ + + + + + +gokrazy showcase + + + + + + + +
+

gokrazy

+
+ + +
+
+

Showcase

+

Written for gokrazy

+

+The following third-party programs specifically target gokrazy: +

+
    +
  • + router7
    + Pure-Go small home internet router +
  • +
  • +avr-x1100w
    +Automatically switches input sources on a Denon AVR-X1100W A/V receiver +depending on which media source is in use (specific to stapelberg’s home network). +
  • +
  • +dornröschen
    +SSH-based backup and storage sync orchestration (specific to stapelberg’s home network). +
  • +
  • +hmgo
    +Minimal HomeMatic house automation central control unit replacement (specific +to stapelberg’s home network). +
  • +
  • +scan2drive
    +scan2drive is a Raspberry Pi 3-based appliance (with a web interface) +for scanning, converting and uploading physical documents to Google +Drive. +
  • +
  • +beatbox
    +beatbox is a Raspberry Pi 3-based toy that combines a Mir:ror and NFC +figurines for playing music stored on the device or directly from Spotify. +
  • +
+ +

+To get your program listed here, just send us a pull request. +

+ +

Successfully tested

+

+The following third-party programs have been successfully used with gokrazy +but might require additional setup: +

+
    +
  • + Prometheus
    + Monitoring system & time series database +
  • + +
  • + Prometheus + node exporter
    Exposes various metrics of the system on + which it is running for use with the + prometheus monitoring and alerting system. +
  • + +
  • + Prometheus + blackbox exporter
    allows blackbox probing of endpoints over + HTTP, HTTPS, DNS, TCP and ICMP for use with the + prometheus monitoring and alerting system. +
  • + +
  • + Grafana
    + The open platform for beautiful analytics and monitoring +
  • +
+ +

No Go software for your idea?

+

+ You can prototype your idea by temporarily using existing software to close + the gap. See Prototyping. +

+
+
+ + +
+ + + + + diff --git a/docs/sitemap.xml b/docs/sitemap.xml new file mode 100644 index 0000000..ea67749 --- /dev/null +++ b/docs/sitemap.xml @@ -0,0 +1,29 @@ + + + + + https://gokrazy.org/ + + + + https://gokrazy.org/platforms/ + + + + https://gokrazy.org/prototyping/ + + + + https://gokrazy.org/quickstart/ + + + + https://gokrazy.org/showcase/ + + + + https://gokrazy.org/modules/ + + + \ No newline at end of file diff --git a/website/config.toml b/website/config.toml new file mode 100644 index 0000000..7dd10b9 --- /dev/null +++ b/website/config.toml @@ -0,0 +1,19 @@ +baseURL = "https://gokrazy.org/" +languageCode = "en-us" +title = "gokrazy" +theme = "gokrazy" +disableKinds = ["RSS", "taxonomyTerm"] +publishDir = "../docs/" +enableRobotsTXT = true + +[markup.goldmark.renderer] +# Required for e.g. tags in markdown articles. +unsafe = true + +[menu] + + [[menu.main]] + name = "github" + title = "Source" + url = "https://github.com/gokrazy/gokrazy" + weight = 60 diff --git a/website/content/_index.html b/website/content/_index.html new file mode 100644 index 0000000..3a40bff --- /dev/null +++ b/website/content/_index.html @@ -0,0 +1,83 @@ +--- +layout: default +title: gokrazy - a pure-Go userland for your Raspberry Pi 3 appliances +menu: + main: + title: "Home" + weight: 1 +--- + +
+ +

gokrazy is a pure-Go userland for your Raspberry Pi 3 appliances

+

+ For a long time, we were unhappy with having to care about security + issues and Linux distribution maintenance on our various Raspberry Pis. +

+

+ Then, we had a crazy idea: what if we got rid of memory-unsafe + languages and all software we don’t strictly need? +

+

+ Turns out this is feasible. gokrazy is the result. +

+
+ +
+
+

Your app(s) + only 4 moving parts

+
    +
  1. the Linux kernel
  2. +
  3. the Raspberry Pi firmware files
  4. +
  5. the Go compiler and standard library
  6. +
  7. the gokrazy userland
  8. +
+

+ All are updated using the same command. +

+ +

Web status interface

+

+ On a regular Linux distribution, we’d largely use systemctl’s start, + stop, restart and status verbs to manage our applications. gokrazy + comes with a convenient web interface for + seeing process status and stopping/restarting processes. +

+ +

Debugging

+

+ Sometimes, an interactive busybox session or a quick + tcpdump run are invaluable. breakglass allows + you to temporarily enable SSH/SCP-based authenticated remote code + execution: scp your statically compiled binary, then run it + interactively via ssh. +

+
+ +
+

Constraints

+

+ Due to no C runtime environment being present, your code must compile + with the environment variable CGO_ENABLED=0. To + cross-compile for the Raspberry Pi 3, use GOARCH=arm64. + If your program still builds, you’re good to go! +

+ +

Network updates

+

+ After building a new gokrazy image on your computer, you can easily + update an existing gokrazy installation in-place thanks to the A/B + partitioning scheme we use. Just specify the -update + flag when building your new image. +

+ +

Minimal state and configuration

+

+ A tiny amount of configuration is built into the images (e.g. + hostname, password, serial console behavior). In general, we prefer + auto-configuration (e.g. DHCP) over config files. If you need more + configurability, you may need to replace some of our programs. +

+
+
diff --git a/website/content/modules.html b/website/content/modules.html new file mode 100644 index 0000000..c8fc29e --- /dev/null +++ b/website/content/modules.html @@ -0,0 +1,30 @@ +--- +layout: default +title: using Go modules +--- + +
+
+

Using Go modules

+ +

pull in repositories from your GOPATH

+

+ By default, Go modules will not look at $GOPATH/src, + i.e. all packages passed to gokr-packer will be downloaded. If you + had unpublished changes or packages in your $GOPATH, + you can use the following steps to declare a Go module and pull it + into the build: +

+
IMPORTPATH=github.com/stapelberg/gibot-i3
+(cd $(go env GOPATH)/src/${IMPORTPATH?} && GO111MODULE=on go mod init ${IMPORTPATH?})
+go mod edit -require ${IMPORTPATH?}@v0.0.0
+go mod edit -replace ${IMPORTPATH?}=$(go env GOPATH)/src/${IMPORTPATH?}
+
+ +

pull in local repositories

+

+ Please see https://github.com/golang/go/wiki/Modules#when-should-i-use-the-replace-directive. +

+ +
+
diff --git a/website/content/platforms.html b/website/content/platforms.html new file mode 100644 index 0000000..adcb230 --- /dev/null +++ b/website/content/platforms.html @@ -0,0 +1,91 @@ +--- +layout: default +title: gokrazy platforms +aliases: + - /platforms.html +menu: + main: + title: "Platforms" + weight: 10 +--- + +
+
+

Supported platforms

+

+ bold appliances are tested in the CI setup on real + hardware and gate new kernel and firmware versions, and hence can be + considered supported. +

+ +

+ Regular appliances are supported in a best-effort way, i.e. they + might be temporarily broken at HEAD. +

+ +

+ The leading github.com in front of package import paths has been omitted for space reasons. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TargetHardwareGOARCHKernel packageFirmware packageAppliances
apu2c4apu2c4amd64rtr7/kernelrtr7/kernel + gokrazy/bakery/cmd/bake
+ rtr7/router7 +
x86-64qemuamd64rtr7/kernelrtr7/kernelgokrazy/bakery/cmd/bake
rpi3braspi3barm64gokrazy/kernelgokrazy/firmware + gokrazy/bakery/cmd/bake
+ stapelberg/avr-x1100w
+ stapelberg/dornröschen
+ stapelberg/hmgo
+ stapelberg/scan2drive +
rpi3b+raspi3b+arm64gokrazy/kernelgokrazy/firmwaregokrazy/bakery/cmd/bake
+ +
+
diff --git a/website/content/prototyping.html b/website/content/prototyping.html new file mode 100644 index 0000000..9805e56 --- /dev/null +++ b/website/content/prototyping.html @@ -0,0 +1,208 @@ +--- +layout: default +title: gokrazy prototyping +aliases: + - /prototyping.html +--- + +
+
+

Prototyping

+

+ To realize the full benefits of gokrazy, you need to use only + software written in Go. If there is no Go software for what you want + to do, creating that piece of software can pose a seemingly + unsurmountable hurdle. To make some quick progress and figure out if + your idea can be implemented, it might make sense to temporarily use + existing software before starting your own implementation. +

+ +

+ This article shows a couple of techniques for getting non-Go + software to work on gokrazy, in increasing order of complexity. +

+ +

+ Note that software which is manually installed like shown + here will not be automatically updated by gokrazy + and hence poses a security risk. Use these techniques only for + prototyping. +

+ +

Go software not written for gokrazy: node-exporter

+

+ The Prometheus node-exporter doesn’t use cgo and needs no + command-line parameters, configuration files or other assets can be + added to the gokr-packer command line. +

+ +

Go software not written for gokrazy: Grafana

+

+ It would not suffice to add Grafana to your gokr-packer + command, as the resulting Grafana binary requires assets, supports + plugins, keeps state, etc. +

+ +

+ Hence, you need to manually install Grafana into a directory + underneath /perm. A convenient way to do that is to + use breakglass + to download the “Standalone Linux Binaries” release from + https://grafana.com/grafana/download?platform=arm. Note + that I am serving the file from my computer because my busybox + version supports neither HTTPS nor DNS. +

+ +
+/tmp/breakglass531810560 # wget http://10.0.0.76:4080/grafana-5.3.2.linux-arm64.tar.gz
+/tmp/breakglass531810560 # tar xf grafana-5.3.2.linux-arm64.tar.gz
+ +

+ We cannot start Grafana yet, as its binary is dynamically + linked. One way to fix this is to place the sources which correspond + to the release you just unpacked (e.g. from + https://github.com/grafana/grafana/tree/v5.3.2) + in your $GOPATH and recompile the binaries: +

+ +
GOARCH=arm64 CGO_ENABLED=1 CC=aarch64-linux-gnu-gcc go install \
+	    -ldflags "-linkmode external -extldflags -static" \
+	    github.com/grafana/grafana/pkg/cmd/...
+ +

+ Note that it is usually easier to set the environment + variable CGO_ENABLED=0 to get a statically linked + binary, but Grafana uses sqlite3, which is written in C, so we + resort to the -ldflags variant. +

+ +

+ At this point, we can start Grafana from breakglass: +

+ +
+/tmp/breakglass531810560 # cd grafana-5.3.2
+/tmp/breakglass531810560/grafana-5.3.2 # wget http://10.0.0.76:4080/grafana-server
+/tmp/breakglass531810560/grafana-5.3.2 # install -m 755 grafana-server bin/ && rm grafana-server
+/tmp/breakglass531810560/grafana-5.3.2 # ./bin/grafana-server
+INFO[10-30|19:27:51] Starting Grafana                         logger=server version=5.0.0 commit=NA compiled=2018-10-30T19:27:51+0100
+…
+ + +

+ To have gokrazy start Grafana, we can use a Go package like this: +

+ +
+package main
+
+import (
+  "log"
+  "syscall"
+)
+
+func main() {
+  const bin = "/perm/grafana/bin/grafana-server"
+  if err := syscall.Exec(bin, []string{bin, "-homepath=/perm/grafana"}, nil); err != nil {
+    log.Fatal(err)
+  }
+}
+
+ +

C software: WireGuard

+ +

+ WireGuard is a modern VPN tunnel, which consists of a Linux kernel + module and a configuration + tool. See rtr7/kernel@c7afbc1f + for how the kernel module was added to the router7 kernel. +

+ +

+ The configuration tool can be statically cross-compiled. We can run + Debian in a Docker container to not mess with our host system: +

+ +
+% mkdir /tmp/wg
+% cd /tmp/wg
+% docker run -t -i debian
+root@d1728eaaa6e1:/# dpkg --add-architecture arm64
+root@d1728eaaa6e1:/# apt update
+root@d1728eaaa6e1:/# apt install libmnl-dev:arm64 libelf-dev:arm64 linux-headers-amd64 crossbuild-essential-arm64 pkg-config wget
+root@d1728eaaa6e1:/# wget https://git.zx2c4.com/WireGuard/snapshot/WireGuard-0.0.20181018.tar.xz
+root@d1728eaaa6e1:/# tar xf WireGuard-0.0.20181018.tar.xz
+root@d1728eaaa6e1:/# cd WireGuard-0.0.20181018/src/tools
+root@d1728eaaa6e1:/# make CC=aarch64-linux-gnu-gcc LDFLAGS=-static
+root@d1728eaaa6e1:/# exit
+% docker cp -L d1728eaaa6e1:/WireGuard-0.0.20181018/src/tools/wg .
+ +

+ Now we can copy and run the wg binary via breakglass: +

+ +
+/tmp/breakglass531810560 # wget http://10.0.0.76:4080/wg
+/tmp/breakglass531810560 # chmod +x wg
+/tmp/breakglass531810560 # ./wg --help
+Usage: ./wg <cmd> [<args>]
+…
+ +

C software: tc

+

+ Linux’s Traffic Control system (used e.g. for traffic shaping) is + configured with the tc tool. +

+ +

+ tc is a special case in that it requires to be + dynamically linked. The different queueing disciplines are + implemented as plugins, and statically linking tc + results in a binary which starts but won’t be able to display or + change queueing disciplines. +

+ +

+ Because gokrazy doesn’t include a C runtime environment, we’ll need + to copy not only the tc binary, but also the dynamic + loader and all required shared libraries. We can run Debian in a + Docker container to not mess with our host system: +

+ +
+% mkdir /tmp/iproute
+% cd /tmp/iproute
+% docker run -t -i debian
+root@6e530a973d45:/# dpkg --add-architecture arm64
+root@6e530a973d45:/# apt update
+root@6e530a973d45:/# apt install iproute2:arm64 qemu-user-static
+root@6e530a973d45:/# LD_TRACE_LOADED_OBJECTS=1 qemu-aarch64-static /sbin/tc
+	libelf.so.1 => /usr/lib/aarch64-linux-gnu/libelf.so.1 (0x00000040008a6000)
+	libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x00000040008cb000)
+	libdl.so.2 => /lib/aarch64-linux-gnu/libdl.so.2 (0x0000004000976000)
+	libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000004000989000)
+	/lib/ld-linux-aarch64.so.1 (0x0000004000870000)
+	libz.so.1 => /lib/aarch64-linux-gnu/libz.so.1 (0x0000004000ad3000)
+root@6e530a973d45:/# exit
+% docker cp -L 6e530a973d45:/sbin/tc .
+% docker cp -L 6e530a973d45:/lib/ld-linux-aarch64.so.1 .
+% docker cp -L 6e530a973d45:/usr/lib/aarch64-linux-gnu/libelf.so.1 .
+% docker cp -L 6e530a973d45:/lib/aarch64-linux-gnu/libm.so.6 .
+% docker cp -L 6e530a973d45:/lib/aarch64-linux-gnu/libdl.so.2 .
+% docker cp -L 6e530a973d45:/lib/aarch64-linux-gnu/libc.so.6 .
+% docker cp -L 6e530a973d45:/lib/aarch64-linux-gnu/libz.so.1 .
+ +

+ Now we can copy the contents of the temporary directory to + e.g. /perm/tc and run the tc command in + breakglass: +

+ +
+/tmp/breakglass531810560 # wget -O- http://10.0.0.76:4080/tc.tar | tar xf -
+/tmp/breakglass531810560 # LD_LIBRARY_PATH=$PWD ./ld-linux-aarch64.so.1 ./tc
+Usage: tc [ OPTIONS ] OBJECT { COMMAND | help }
+…
+ +
+
diff --git a/website/content/quickstart.html b/website/content/quickstart.html new file mode 100644 index 0000000..d7c75d5 --- /dev/null +++ b/website/content/quickstart.html @@ -0,0 +1,74 @@ +--- +title: gokrazy quickstart +aliases: + - /quickstart.html +menu: + main: + title: "Quickstart" + weight: 20 +--- + +
+
+

Get a Raspberry Pi 3 (no other model)

+

+ Currently, the Raspberry Pi 3 is the only + model supported. Many people assume the Raspberry Pi Zero W + could be used as well. Unfortunately, it uses the older + BCM2835 SoC, which is not arm64, so gokrazy won’t run on + it. See + also stapelberg’s + reddit comment about supported hardware. +

+ +

Install Go

+

+ If you don’t already have Go installed, install the latest Go version. +

+ +

Install the gokrazy packer

+
INSTANCE=gokrazy/hello; mkdir -p ~/${INSTANCE?} && cd ~/${INSTANCE?} && echo module ${INSTANCE?} > go.mod
+go get -u github.com/gokrazy/tools/cmd/gokr-packer
+ +

Overwrite an SD card with gokrazy

+

+ Plug an SD card into your card reader and locate its device node by checking dmesg | tail. In this example, we’ll assume the SD card is accessible as /dev/sdb. +

+

+ To overwrite the entire SD card /dev/sdb with a gokrazy installation running a hello world program, use: +

+
cd ~/gokrazy/hello
+gokr-packer -overwrite=/dev/sdb github.com/gokrazy/hello github.com/gokrazy/serial-busybox
+

+ The gokr-packer command above will result in log output like this: +

+
2017/03/01 20:59:55 packer.go:85: installing [github.com/gokrazy/hello]
+2017/03/01 20:59:56 packer.go:131: partitioning /dev/sdb
+2017/03/01 20:59:56 parttable.go:40: device holds 15931539456 bytes
+2017/03/01 20:59:56 packer.go:139: waiting for /dev/sdb1 to appear
+If your applications need to store persistent data, create a file system using e.g.:
+
+	mkfs.ext4 /dev/sdb4
+
+To boot gokrazy, plug the SD card into a Raspberry Pi 3 (no other model supported)
+
+To interact with the device, gokrazy provides a web interface reachable at:
+
+	http://gokrazy:<automatically-generated-random-password>@gokrazy/
+
+There will be not be any other output (no HDMI, no serial console, etc.)
+

+ After booting from this SD card, your Raspberry Pi 3 will: +

+ The only way for you to interact with the device is via the + web interface (unless the installed programs provide other + ways). There will be no HDMI output, no serial console, etc. +

+
+
diff --git a/website/content/showcase.html b/website/content/showcase.html new file mode 100644 index 0000000..49fc7c7 --- /dev/null +++ b/website/content/showcase.html @@ -0,0 +1,95 @@ +--- +layout: default +title: gokrazy showcase +aliases: + - /showcase.html +menu: + main: + title: "Showcase" + weight: 30 +--- + +
+
+

Showcase

+

Written for gokrazy

+

+The following third-party programs specifically target gokrazy: +

+ + +

+To get your program listed here, just send us a pull request. +

+ +

Successfully tested

+

+The following third-party programs have been successfully used with gokrazy +but might require additional setup: +

+ + +

No Go software for your idea?

+

+ You can prototype your idea by temporarily using existing software to close + the gap. See Prototyping. +

+
+
diff --git a/website/docs/CNAME b/website/docs/CNAME new file mode 100644 index 0000000..eacc754 --- /dev/null +++ b/website/docs/CNAME @@ -0,0 +1 @@ +gokrazy.org diff --git a/website/docs/favicon.ico b/website/docs/favicon.ico new file mode 100644 index 0000000..32c597c Binary files /dev/null and b/website/docs/favicon.ico differ diff --git a/website/docs/index.html b/website/docs/index.html new file mode 100644 index 0000000..d28822b --- /dev/null +++ b/website/docs/index.html @@ -0,0 +1,132 @@ + + + + + + +gokrazy - a pure-Go userland for your Raspberry Pi 3 appliances + + + + + + + +
+

gokrazy

+
+ + + +
+ +

gokrazy is a pure-Go userland for your Raspberry Pi 3 appliances

+

+ For a long time, we were unhappy with having to care about security + issues and Linux distribution maintenance on our various Raspberry Pis. +

+

+ Then, we had a crazy idea: what if we got rid of memory-unsafe + languages and all software we don’t strictly need? +

+

+ Turns out this is feasible. gokrazy is the result. +

+
+ +
+
+

Your app(s) + only 4 moving parts

+
    +
  1. the Linux kernel
  2. +
  3. the Raspberry Pi firmware files
  4. +
  5. the Go compiler and standard library
  6. +
  7. the gokrazy userland
  8. +
+

+ All are updated using the same command. +

+ +

Web status interface

+

+ On a regular Linux distribution, we’d largely use systemctl’s start, + stop, restart and status verbs to manage our applications. gokrazy + comes with a convenient web interface for + seeing process status and stopping/restarting processes. +

+ +

Debugging

+

+ Sometimes, an interactive busybox session or a quick + tcpdump run are invaluable. breakglass allows + you to temporarily enable SSH/SCP-based authenticated remote code + execution: scp your statically compiled binary, then run it + interactively via ssh. +

+
+ +
+

Constraints

+

+ Due to no C runtime environment being present, your code must compile + with the environment variable CGO_ENABLED=0. To + cross-compile for the Raspberry Pi 3, use GOARCH=arm64. + If your program still builds, you’re good to go! +

+ +

Network updates

+

+ After building a new gokrazy image on your computer, you can easily + update an existing gokrazy installation in-place thanks to the A/B + partitioning scheme we use. Just specify the -update + flag when building your new image. +

+ +

Minimal state and configuration

+

+ A tiny amount of configuration is built into the images (e.g. + hostname, password, serial console behavior). In general, we prefer + auto-configuration (e.g. DHCP) over config files. If you need more + configurability, you may need to replace some of our programs. +

+
+
+ + + +
+ + + + + diff --git a/website/docs/jumbotron-narrow.css b/website/docs/jumbotron-narrow.css new file mode 100644 index 0000000..fb7c49a --- /dev/null +++ b/website/docs/jumbotron-narrow.css @@ -0,0 +1,79 @@ +/* Space out content a bit */ +body { + padding-top: 20px; + padding-bottom: 20px; +} + +/* Everything but the jumbotron gets side spacing for mobile first views */ +.header, +.marketing, +.footer { + padding-right: 15px; + padding-left: 15px; +} + +/* Custom page header */ +.header { + border-bottom: 1px solid #e5e5e5; +} +/* Make the masthead heading the same height as the navigation */ +.header h3 { + padding-bottom: 19px; + margin-top: 0; + margin-bottom: 0; + line-height: 40px; +} + +/* Custom page footer */ +.footer { + padding-top: 19px; + color: #777; + border-top: 1px solid #e5e5e5; +} + +/* Customize container */ +@media (min-width: 768px) { + .container { + max-width: 730px; + } +} +.container-narrow > hr { + margin: 30px 0; +} + +/* Main marketing message and sign up button */ +.jumbotron { + text-align: center; + border-bottom: 1px solid #e5e5e5; +} +.jumbotron .btn { + padding: 14px 24px; + font-size: 21px; +} + +/* Supporting marketing content */ +.marketing { + margin: 40px 0; +} +.marketing p + h4 { + margin-top: 28px; +} + +/* Responsive: Portrait tablets and up */ +@media screen and (min-width: 768px) { + /* Remove the padding we set earlier */ + .header, + .marketing, + .footer { + padding-right: 0; + padding-left: 0; + } + /* Space out the masthead */ + .header { + margin-bottom: 30px; + } + /* Remove the bottom border on the jumbotron for visual effect */ + .jumbotron { + border-bottom: 0; + } +} diff --git a/website/docs/jumbotron-narrow.min.css b/website/docs/jumbotron-narrow.min.css new file mode 100644 index 0000000..0c5a883 --- /dev/null +++ b/website/docs/jumbotron-narrow.min.css @@ -0,0 +1 @@ +body{padding-top:20px;padding-bottom:20px}.header,.marketing,.footer{padding-right:15px;padding-left:15px}.header{border-bottom:1px solid #e5e5e5}.header h3{padding-bottom:19px;margin-top:0;margin-bottom:0;line-height:40px}.footer{padding-top:19px;color:#777;border-top:1px solid #e5e5e5}@media(min-width:768px){.container{max-width:730px}}.container-narrow>hr{margin:30px 0}.jumbotron{text-align:center;border-bottom:1px solid #e5e5e5}.jumbotron .btn{padding:14px 24px;font-size:21px}.marketing{margin:40px 0}.marketing p+h4{margin-top:28px}@media screen and (min-width:768px){.header,.marketing,.footer{padding-right:0;padding-left:0}.header{margin-bottom:30px}.jumbotron{border-bottom:0}} \ No newline at end of file diff --git a/website/docs/logo.png b/website/docs/logo.png new file mode 100644 index 0000000..05b5286 Binary files /dev/null and b/website/docs/logo.png differ diff --git a/website/docs/logo.svg b/website/docs/logo.svg new file mode 100644 index 0000000..927ce51 --- /dev/null +++ b/website/docs/logo.svg @@ -0,0 +1,663 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/website/docs/modules/index.html b/website/docs/modules/index.html new file mode 100644 index 0000000..42e7aa1 --- /dev/null +++ b/website/docs/modules/index.html @@ -0,0 +1,80 @@ + + + + + +using Go modules + + + + + + + +
+

gokrazy

+
+ + +
+
+

Using Go modules

+ +

pull in repositories from your GOPATH

+

+ By default, Go modules will not look at $GOPATH/src, + i.e. all packages passed to gokr-packer will be downloaded. If you + had unpublished changes or packages in your $GOPATH, + you can use the following steps to declare a Go module and pull it + into the build: +

+
IMPORTPATH=github.com/stapelberg/gibot-i3
+(cd $(go env GOPATH)/src/${IMPORTPATH?} && GO111MODULE=on go mod init ${IMPORTPATH?})
+go mod edit -require ${IMPORTPATH?}@v0.0.0
+go mod edit -replace ${IMPORTPATH?}=$(go env GOPATH)/src/${IMPORTPATH?}
+
+ +

pull in local repositories

+

+ Please see https://github.com/golang/go/wiki/Modules#when-should-i-use-the-replace-directive. +

+ +
+
+ + +
+ + + + + diff --git a/website/docs/overview.png b/website/docs/overview.png new file mode 100644 index 0000000..6e6f2bc Binary files /dev/null and b/website/docs/overview.png differ diff --git a/website/docs/platforms.html b/website/docs/platforms.html new file mode 100644 index 0000000..f057b1d --- /dev/null +++ b/website/docs/platforms.html @@ -0,0 +1 @@ +https://gokrazy.org/platforms/ \ No newline at end of file diff --git a/website/docs/platforms/index.html b/website/docs/platforms/index.html new file mode 100644 index 0000000..a90f102 --- /dev/null +++ b/website/docs/platforms/index.html @@ -0,0 +1,135 @@ + + + + + +gokrazy platforms + + + + + + + +
+

gokrazy

+
+ + +
+
+

Supported platforms

+

+ bold appliances are tested in the CI setup on real + hardware and gate new kernel and firmware versions, and hence can be + considered supported. +

+ +

+ Regular appliances are supported in a best-effort way, i.e. they + might be temporarily broken at HEAD. +

+ +

+ The leading github.com in front of package import paths has been omitted for space reasons. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TargetHardwareGOARCHKernel packageFirmware packageAppliances
apu2c4apu2c4amd64rtr7/kernelrtr7/kernel + gokrazy/bakery/cmd/bake
+ rtr7/router7 +
x86-64qemuamd64rtr7/kernelrtr7/kernelgokrazy/bakery/cmd/bake
rpi3braspi3barm64gokrazy/kernelgokrazy/firmware + gokrazy/bakery/cmd/bake
+ stapelberg/avr-x1100w
+ stapelberg/dornröschen
+ stapelberg/hmgo
+ stapelberg/scan2drive +
rpi3b+raspi3b+arm64gokrazy/kernelgokrazy/firmwaregokrazy/bakery/cmd/bake
+ +
+
+ + +
+ + + + + diff --git a/website/docs/prototyping.html b/website/docs/prototyping.html new file mode 100644 index 0000000..68aa245 --- /dev/null +++ b/website/docs/prototyping.html @@ -0,0 +1 @@ +https://gokrazy.org/prototyping/ \ No newline at end of file diff --git a/website/docs/prototyping/index.html b/website/docs/prototyping/index.html new file mode 100644 index 0000000..7268b60 --- /dev/null +++ b/website/docs/prototyping/index.html @@ -0,0 +1,256 @@ + + + + + +gokrazy prototyping + + + + + + + +
+

gokrazy

+
+ + +
+
+

Prototyping

+

+ To realize the full benefits of gokrazy, you need to use only + software written in Go. If there is no Go software for what you want + to do, creating that piece of software can pose a seemingly + unsurmountable hurdle. To make some quick progress and figure out if + your idea can be implemented, it might make sense to temporarily use + existing software before starting your own implementation. +

+ +

+ This article shows a couple of techniques for getting non-Go + software to work on gokrazy, in increasing order of complexity. +

+ +

+ Note that software which is manually installed like shown + here will not be automatically updated by gokrazy + and hence poses a security risk. Use these techniques only for + prototyping. +

+ +

Go software not written for gokrazy: node-exporter

+

+ The Prometheus node-exporter doesn’t use cgo and needs no + command-line parameters, configuration files or other assets can be + added to the gokr-packer command line. +

+ +

Go software not written for gokrazy: Grafana

+

+ It would not suffice to add Grafana to your gokr-packer + command, as the resulting Grafana binary requires assets, supports + plugins, keeps state, etc. +

+ +

+ Hence, you need to manually install Grafana into a directory + underneath /perm. A convenient way to do that is to + use breakglass + to download the “Standalone Linux Binaries” release from + https://grafana.com/grafana/download?platform=arm. Note + that I am serving the file from my computer because my busybox + version supports neither HTTPS nor DNS. +

+ +
+/tmp/breakglass531810560 # wget http://10.0.0.76:4080/grafana-5.3.2.linux-arm64.tar.gz
+/tmp/breakglass531810560 # tar xf grafana-5.3.2.linux-arm64.tar.gz
+ +

+ We cannot start Grafana yet, as its binary is dynamically + linked. One way to fix this is to place the sources which correspond + to the release you just unpacked (e.g. from + https://github.com/grafana/grafana/tree/v5.3.2) + in your $GOPATH and recompile the binaries: +

+ +
GOARCH=arm64 CGO_ENABLED=1 CC=aarch64-linux-gnu-gcc go install \
+	    -ldflags "-linkmode external -extldflags -static" \
+	    github.com/grafana/grafana/pkg/cmd/...
+ +

+ Note that it is usually easier to set the environment + variable CGO_ENABLED=0 to get a statically linked + binary, but Grafana uses sqlite3, which is written in C, so we + resort to the -ldflags variant. +

+ +

+ At this point, we can start Grafana from breakglass: +

+ +
+/tmp/breakglass531810560 # cd grafana-5.3.2
+/tmp/breakglass531810560/grafana-5.3.2 # wget http://10.0.0.76:4080/grafana-server
+/tmp/breakglass531810560/grafana-5.3.2 # install -m 755 grafana-server bin/ && rm grafana-server
+/tmp/breakglass531810560/grafana-5.3.2 # ./bin/grafana-server
+INFO[10-30|19:27:51] Starting Grafana                         logger=server version=5.0.0 commit=NA compiled=2018-10-30T19:27:51+0100
+…
+ + +

+ To have gokrazy start Grafana, we can use a Go package like this: +

+ +
+package main
+
+import (
+  "log"
+  "syscall"
+)
+
+func main() {
+  const bin = "/perm/grafana/bin/grafana-server"
+  if err := syscall.Exec(bin, []string{bin, "-homepath=/perm/grafana"}, nil); err != nil {
+    log.Fatal(err)
+  }
+}
+
+ +

C software: WireGuard

+ +

+ WireGuard is a modern VPN tunnel, which consists of a Linux kernel + module and a configuration + tool. See rtr7/kernel@c7afbc1f + for how the kernel module was added to the router7 kernel. +

+ +

+ The configuration tool can be statically cross-compiled. We can run + Debian in a Docker container to not mess with our host system: +

+ +
+% mkdir /tmp/wg
+% cd /tmp/wg
+% docker run -t -i debian
+root@d1728eaaa6e1:/# dpkg --add-architecture arm64
+root@d1728eaaa6e1:/# apt update
+root@d1728eaaa6e1:/# apt install libmnl-dev:arm64 libelf-dev:arm64 linux-headers-amd64 crossbuild-essential-arm64 pkg-config wget
+root@d1728eaaa6e1:/# wget https://git.zx2c4.com/WireGuard/snapshot/WireGuard-0.0.20181018.tar.xz
+root@d1728eaaa6e1:/# tar xf WireGuard-0.0.20181018.tar.xz
+root@d1728eaaa6e1:/# cd WireGuard-0.0.20181018/src/tools
+root@d1728eaaa6e1:/# make CC=aarch64-linux-gnu-gcc LDFLAGS=-static
+root@d1728eaaa6e1:/# exit
+% docker cp -L d1728eaaa6e1:/WireGuard-0.0.20181018/src/tools/wg .
+ +

+ Now we can copy and run the wg binary via breakglass: +

+ +
+/tmp/breakglass531810560 # wget http://10.0.0.76:4080/wg
+/tmp/breakglass531810560 # chmod +x wg
+/tmp/breakglass531810560 # ./wg --help
+Usage: ./wg <cmd> [<args>]
+…
+ +

C software: tc

+

+ Linux’s Traffic Control system (used e.g. for traffic shaping) is + configured with the tc tool. +

+ +

+ tc is a special case in that it requires to be + dynamically linked. The different queueing disciplines are + implemented as plugins, and statically linking tc + results in a binary which starts but won’t be able to display or + change queueing disciplines. +

+ +

+ Because gokrazy doesn’t include a C runtime environment, we’ll need + to copy not only the tc binary, but also the dynamic + loader and all required shared libraries. We can run Debian in a + Docker container to not mess with our host system: +

+ +
+% mkdir /tmp/iproute
+% cd /tmp/iproute
+% docker run -t -i debian
+root@6e530a973d45:/# dpkg --add-architecture arm64
+root@6e530a973d45:/# apt update
+root@6e530a973d45:/# apt install iproute2:arm64 qemu-user-static
+root@6e530a973d45:/# LD_TRACE_LOADED_OBJECTS=1 qemu-aarch64-static /sbin/tc
+	libelf.so.1 => /usr/lib/aarch64-linux-gnu/libelf.so.1 (0x00000040008a6000)
+	libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x00000040008cb000)
+	libdl.so.2 => /lib/aarch64-linux-gnu/libdl.so.2 (0x0000004000976000)
+	libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000004000989000)
+	/lib/ld-linux-aarch64.so.1 (0x0000004000870000)
+	libz.so.1 => /lib/aarch64-linux-gnu/libz.so.1 (0x0000004000ad3000)
+root@6e530a973d45:/# exit
+% docker cp -L 6e530a973d45:/sbin/tc .
+% docker cp -L 6e530a973d45:/lib/ld-linux-aarch64.so.1 .
+% docker cp -L 6e530a973d45:/usr/lib/aarch64-linux-gnu/libelf.so.1 .
+% docker cp -L 6e530a973d45:/lib/aarch64-linux-gnu/libm.so.6 .
+% docker cp -L 6e530a973d45:/lib/aarch64-linux-gnu/libdl.so.2 .
+% docker cp -L 6e530a973d45:/lib/aarch64-linux-gnu/libc.so.6 .
+% docker cp -L 6e530a973d45:/lib/aarch64-linux-gnu/libz.so.1 .
+ +

+ Now we can copy the contents of the temporary directory to + e.g. /perm/tc and run the tc command in + breakglass: +

+ +
+/tmp/breakglass531810560 # wget -O- http://10.0.0.76:4080/tc.tar | tar xf -
+/tmp/breakglass531810560 # LD_LIBRARY_PATH=$PWD ./ld-linux-aarch64.so.1 ./tc
+Usage: tc [ OPTIONS ] OBJECT { COMMAND | help }
+…
+ +
+
+ + +
+ + + + + diff --git a/website/docs/quickstart.html b/website/docs/quickstart.html new file mode 100644 index 0000000..8ef6dd4 --- /dev/null +++ b/website/docs/quickstart.html @@ -0,0 +1 @@ +https://gokrazy.org/quickstart/ \ No newline at end of file diff --git a/website/docs/quickstart/index.html b/website/docs/quickstart/index.html new file mode 100644 index 0000000..35ae262 --- /dev/null +++ b/website/docs/quickstart/index.html @@ -0,0 +1,119 @@ + + + + + +gokrazy quickstart + + + + + + + +
+

gokrazy

+
+ + +
+
+

Get a Raspberry Pi 3 (no other model)

+

+ Currently, the Raspberry Pi 3 is the only + model supported. Many people assume the Raspberry Pi Zero W + could be used as well. Unfortunately, it uses the older + BCM2835 SoC, which is not arm64, so gokrazy won’t run on + it. See + also stapelberg’s + reddit comment about supported hardware. +

+ +

Install Go

+

+ If you don’t already have Go installed, install the latest Go version. +

+ +

Install the gokrazy packer

+
INSTANCE=gokrazy/hello; mkdir -p ~/${INSTANCE?} && cd ~/${INSTANCE?} && echo module ${INSTANCE?} > go.mod
+go get -u github.com/gokrazy/tools/cmd/gokr-packer
+ +

Overwrite an SD card with gokrazy

+

+ Plug an SD card into your card reader and locate its device node by checking dmesg | tail. In this example, we’ll assume the SD card is accessible as /dev/sdb. +

+

+ To overwrite the entire SD card /dev/sdb with a gokrazy installation running a hello world program, use: +

+
cd ~/gokrazy/hello
+gokr-packer -overwrite=/dev/sdb github.com/gokrazy/hello github.com/gokrazy/serial-busybox
+

+ The gokr-packer command above will result in log output like this: +

+
2017/03/01 20:59:55 packer.go:85: installing [github.com/gokrazy/hello]
+2017/03/01 20:59:56 packer.go:131: partitioning /dev/sdb
+2017/03/01 20:59:56 parttable.go:40: device holds 15931539456 bytes
+2017/03/01 20:59:56 packer.go:139: waiting for /dev/sdb1 to appear
+If your applications need to store persistent data, create a file system using e.g.:
+
+	mkfs.ext4 /dev/sdb4
+
+To boot gokrazy, plug the SD card into a Raspberry Pi 3 (no other model supported)
+
+To interact with the device, gokrazy provides a web interface reachable at:
+
+	http://gokrazy:<automatically-generated-random-password>@gokrazy/
+
+There will be not be any other output (no HDMI, no serial console, etc.)
+

+ After booting from this SD card, your Raspberry Pi 3 will: +

    +
  • obtain an IP address for hostname “gokrazy” via DHCP (IPv4) and SLAAC (IPv6)
  • +
  • synchronize the clock using NTP
  • +
  • expose a password-authenticated web interface on private IP addresses
    + (the default password can be recovered from ~/.config/gokrazy/http-password.txt)
  • +
  • supervise all installed programs (only the hello world program in this example)
  • +
+ The only way for you to interact with the device is via the + web interface (unless the installed programs provide other + ways). There will be no HDMI output, no serial console, etc. +

+
+
+ + +
+ + + + + diff --git a/website/docs/robots.txt b/website/docs/robots.txt new file mode 100644 index 0000000..4f9540b --- /dev/null +++ b/website/docs/robots.txt @@ -0,0 +1 @@ +User-agent: * \ No newline at end of file diff --git a/website/docs/showcase.html b/website/docs/showcase.html new file mode 100644 index 0000000..efde410 --- /dev/null +++ b/website/docs/showcase.html @@ -0,0 +1 @@ +https://gokrazy.org/showcase/ \ No newline at end of file diff --git a/website/docs/showcase/index.html b/website/docs/showcase/index.html new file mode 100644 index 0000000..b082ed5 --- /dev/null +++ b/website/docs/showcase/index.html @@ -0,0 +1,139 @@ + + + + + +gokrazy showcase + + + + + + + +
+

gokrazy

+
+ + +
+
+

Showcase

+

Written for gokrazy

+

+The following third-party programs specifically target gokrazy: +

+
    +
  • + router7
    + Pure-Go small home internet router +
  • +
  • +avr-x1100w
    +Automatically switches input sources on a Denon AVR-X1100W A/V receiver +depending on which media source is in use (specific to stapelberg’s home network). +
  • +
  • +dornröschen
    +SSH-based backup and storage sync orchestration (specific to stapelberg’s home network). +
  • +
  • +hmgo
    +Minimal HomeMatic house automation central control unit replacement (specific +to stapelberg’s home network). +
  • +
  • +scan2drive
    +scan2drive is a Raspberry Pi 3-based appliance (with a web interface) +for scanning, converting and uploading physical documents to Google +Drive. +
  • +
  • +beatbox
    +beatbox is a Raspberry Pi 3-based toy that combines a Mir:ror and NFC +figurines for playing music stored on the device or directly from Spotify. +
  • +
+ +

+To get your program listed here, just send us a pull request. +

+ +

Successfully tested

+

+The following third-party programs have been successfully used with gokrazy +but might require additional setup: +

+
    +
  • + Prometheus
    + Monitoring system & time series database +
  • + +
  • + Prometheus + node exporter
    Exposes various metrics of the system on + which it is running for use with the + prometheus monitoring and alerting system. +
  • + +
  • + Prometheus + blackbox exporter
    allows blackbox probing of endpoints over + HTTP, HTTPS, DNS, TCP and ICMP for use with the + prometheus monitoring and alerting system. +
  • + +
  • + Grafana
    + The open platform for beautiful analytics and monitoring +
  • +
+ +

No Go software for your idea?

+

+ You can prototype your idea by temporarily using existing software to close + the gap. See Prototyping. +

+
+
+ + +
+ + + + + diff --git a/website/docs/sitemap.xml b/website/docs/sitemap.xml new file mode 100644 index 0000000..ea67749 --- /dev/null +++ b/website/docs/sitemap.xml @@ -0,0 +1,29 @@ + + + + + https://gokrazy.org/ + + + + https://gokrazy.org/platforms/ + + + + https://gokrazy.org/prototyping/ + + + + https://gokrazy.org/quickstart/ + + + + https://gokrazy.org/showcase/ + + + + https://gokrazy.org/modules/ + + + \ No newline at end of file diff --git a/website/resources/_gen/assets/scss/sass/sidebar.scss_f300667da4f5b5f84e1a9e0702b2fdde.content b/website/resources/_gen/assets/scss/sass/sidebar.scss_f300667da4f5b5f84e1a9e0702b2fdde.content new file mode 100644 index 0000000..ab616f9 --- /dev/null +++ b/website/resources/_gen/assets/scss/sass/sidebar.scss_f300667da4f5b5f84e1a9e0702b2fdde.content @@ -0,0 +1,19 @@ +.bd-toc { + position: sticky; + top: 4rem; + height: calc(100vh - 4rem); + overflow-y: auto; } + +.bd-toc ul { + list-style: none; + padding-left: 1em; + border-left: 1px solid #eee; } + +.bd-toc li { + margin-top: 1em; + margin-bottom: 1em; } + +/* TODO: move this to a separate style sheet */ +.bigbutton { + margin-left: 1em; + margin-right: 1em; } diff --git a/website/resources/_gen/assets/scss/sass/sidebar.scss_f300667da4f5b5f84e1a9e0702b2fdde.json b/website/resources/_gen/assets/scss/sass/sidebar.scss_f300667da4f5b5f84e1a9e0702b2fdde.json new file mode 100644 index 0000000..d3d61f1 --- /dev/null +++ b/website/resources/_gen/assets/scss/sass/sidebar.scss_f300667da4f5b5f84e1a9e0702b2fdde.json @@ -0,0 +1 @@ +{"Target":"sass/sidebar.css","MediaType":"text/css","Data":{}} \ No newline at end of file diff --git a/website/static/CNAME b/website/static/CNAME new file mode 100644 index 0000000..eacc754 --- /dev/null +++ b/website/static/CNAME @@ -0,0 +1 @@ +gokrazy.org diff --git a/website/static/favicon.ico b/website/static/favicon.ico new file mode 100644 index 0000000..32c597c Binary files /dev/null and b/website/static/favicon.ico differ diff --git a/website/static/jumbotron-narrow.css b/website/static/jumbotron-narrow.css new file mode 100644 index 0000000..fb7c49a --- /dev/null +++ b/website/static/jumbotron-narrow.css @@ -0,0 +1,79 @@ +/* Space out content a bit */ +body { + padding-top: 20px; + padding-bottom: 20px; +} + +/* Everything but the jumbotron gets side spacing for mobile first views */ +.header, +.marketing, +.footer { + padding-right: 15px; + padding-left: 15px; +} + +/* Custom page header */ +.header { + border-bottom: 1px solid #e5e5e5; +} +/* Make the masthead heading the same height as the navigation */ +.header h3 { + padding-bottom: 19px; + margin-top: 0; + margin-bottom: 0; + line-height: 40px; +} + +/* Custom page footer */ +.footer { + padding-top: 19px; + color: #777; + border-top: 1px solid #e5e5e5; +} + +/* Customize container */ +@media (min-width: 768px) { + .container { + max-width: 730px; + } +} +.container-narrow > hr { + margin: 30px 0; +} + +/* Main marketing message and sign up button */ +.jumbotron { + text-align: center; + border-bottom: 1px solid #e5e5e5; +} +.jumbotron .btn { + padding: 14px 24px; + font-size: 21px; +} + +/* Supporting marketing content */ +.marketing { + margin: 40px 0; +} +.marketing p + h4 { + margin-top: 28px; +} + +/* Responsive: Portrait tablets and up */ +@media screen and (min-width: 768px) { + /* Remove the padding we set earlier */ + .header, + .marketing, + .footer { + padding-right: 0; + padding-left: 0; + } + /* Space out the masthead */ + .header { + margin-bottom: 30px; + } + /* Remove the bottom border on the jumbotron for visual effect */ + .jumbotron { + border-bottom: 0; + } +} diff --git a/website/static/jumbotron-narrow.min.css b/website/static/jumbotron-narrow.min.css new file mode 100644 index 0000000..0c5a883 --- /dev/null +++ b/website/static/jumbotron-narrow.min.css @@ -0,0 +1 @@ +body{padding-top:20px;padding-bottom:20px}.header,.marketing,.footer{padding-right:15px;padding-left:15px}.header{border-bottom:1px solid #e5e5e5}.header h3{padding-bottom:19px;margin-top:0;margin-bottom:0;line-height:40px}.footer{padding-top:19px;color:#777;border-top:1px solid #e5e5e5}@media(min-width:768px){.container{max-width:730px}}.container-narrow>hr{margin:30px 0}.jumbotron{text-align:center;border-bottom:1px solid #e5e5e5}.jumbotron .btn{padding:14px 24px;font-size:21px}.marketing{margin:40px 0}.marketing p+h4{margin-top:28px}@media screen and (min-width:768px){.header,.marketing,.footer{padding-right:0;padding-left:0}.header{margin-bottom:30px}.jumbotron{border-bottom:0}} \ No newline at end of file diff --git a/website/static/logo.png b/website/static/logo.png new file mode 100644 index 0000000..05b5286 Binary files /dev/null and b/website/static/logo.png differ diff --git a/website/static/logo.svg b/website/static/logo.svg new file mode 100644 index 0000000..927ce51 --- /dev/null +++ b/website/static/logo.svg @@ -0,0 +1,663 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/website/static/overview.png b/website/static/overview.png new file mode 100644 index 0000000..6e6f2bc Binary files /dev/null and b/website/static/overview.png differ diff --git a/website/themes/gokrazy/LICENSE b/website/themes/gokrazy/LICENSE new file mode 100644 index 0000000..faff36e --- /dev/null +++ b/website/themes/gokrazy/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2020 YOUR_NAME_HERE + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/website/themes/gokrazy/archetypes/default.md b/website/themes/gokrazy/archetypes/default.md new file mode 100644 index 0000000..ac36e06 --- /dev/null +++ b/website/themes/gokrazy/archetypes/default.md @@ -0,0 +1,2 @@ ++++ ++++ diff --git a/website/themes/gokrazy/assets/sass/sidebar.scss b/website/themes/gokrazy/assets/sass/sidebar.scss new file mode 100644 index 0000000..d69786f --- /dev/null +++ b/website/themes/gokrazy/assets/sass/sidebar.scss @@ -0,0 +1,23 @@ +.bd-toc { + position: sticky; + top: 4rem; + height: calc(100vh - 4rem); + overflow-y: auto +} + +.bd-toc ul { + list-style: none; + padding-left: 1em; + border-left: 1px solid #eee; +} + +.bd-toc li { + margin-top: 1em; + margin-bottom: 1em; +} + +/* TODO: move this to a separate style sheet */ +.bigbutton { + margin-left: 1em; + margin-right: 1em; +} diff --git a/website/themes/gokrazy/layouts/404.html b/website/themes/gokrazy/layouts/404.html new file mode 100644 index 0000000..e69de29 diff --git a/website/themes/gokrazy/layouts/_default/baseof.html b/website/themes/gokrazy/layouts/_default/baseof.html new file mode 100644 index 0000000..355f61f --- /dev/null +++ b/website/themes/gokrazy/layouts/_default/baseof.html @@ -0,0 +1,15 @@ + + + {{- partial "head.html" . -}} + +
+ + {{- partial "header.html" . -}} + + {{ block "main" . }} + {{ end }} + + {{- partial "footer.html" . -}} +
+ + diff --git a/website/themes/gokrazy/layouts/_default/list.html b/website/themes/gokrazy/layouts/_default/list.html new file mode 100644 index 0000000..7d558b2 --- /dev/null +++ b/website/themes/gokrazy/layouts/_default/list.html @@ -0,0 +1,32 @@ +{{ define "main" }} +
+
+ + {{- partial "nav.html" . -}} + +

list template

+ +{{ .Content }} + + + +
+ +

+ © 2017 gokrazy authors (Michael Stapelberg and contributors) +

+
+
+ +
+
+{{ end }} + diff --git a/website/themes/gokrazy/layouts/_default/single.html b/website/themes/gokrazy/layouts/_default/single.html new file mode 100644 index 0000000..9983b08 --- /dev/null +++ b/website/themes/gokrazy/layouts/_default/single.html @@ -0,0 +1,3 @@ +{{ define "main" }} +{{ .Content }} +{{ end }} diff --git a/website/themes/gokrazy/layouts/index.html b/website/themes/gokrazy/layouts/index.html new file mode 100644 index 0000000..46c82c0 --- /dev/null +++ b/website/themes/gokrazy/layouts/index.html @@ -0,0 +1,5 @@ +{{ define "main" }} + +{{ .Content }} + +{{ end }} diff --git a/website/themes/gokrazy/layouts/partials/footer.html b/website/themes/gokrazy/layouts/partials/footer.html new file mode 100644 index 0000000..ab31a89 --- /dev/null +++ b/website/themes/gokrazy/layouts/partials/footer.html @@ -0,0 +1,6 @@ + + + + diff --git a/website/themes/gokrazy/layouts/partials/head.html b/website/themes/gokrazy/layouts/partials/head.html new file mode 100644 index 0000000..8f0a492 --- /dev/null +++ b/website/themes/gokrazy/layouts/partials/head.html @@ -0,0 +1,18 @@ + + + + +{{ .Title }} + + + + + + diff --git a/website/themes/gokrazy/layouts/partials/header.html b/website/themes/gokrazy/layouts/partials/header.html new file mode 100644 index 0000000..08cdedf --- /dev/null +++ b/website/themes/gokrazy/layouts/partials/header.html @@ -0,0 +1,4 @@ +
+ {{- partial "nav.html" . -}} +

gokrazy

+
diff --git a/website/themes/gokrazy/layouts/partials/nav.html b/website/themes/gokrazy/layouts/partials/nav.html new file mode 100644 index 0000000..e1d1122 --- /dev/null +++ b/website/themes/gokrazy/layouts/partials/nav.html @@ -0,0 +1,9 @@ + diff --git a/website/themes/gokrazy/theme.toml b/website/themes/gokrazy/theme.toml new file mode 100644 index 0000000..228c1fc --- /dev/null +++ b/website/themes/gokrazy/theme.toml @@ -0,0 +1,21 @@ +# theme.toml template for a Hugo theme +# See https://github.com/gohugoio/hugoThemes#themetoml for an example + +name = "gokrazy" +license = "MIT" +licenselink = "https://github.com/yourname/yourtheme/blob/master/LICENSE" +description = "" +homepage = "http://example.com/" +tags = [] +features = [] +min_version = "0.41.0" + +[author] + name = "" + homepage = "" + +# If porting an existing theme +[original] + name = "" + homepage = "" + repo = ""