initial commit
7
.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
.devcontainer/
|
||||
.hugo_build.lock
|
||||
|
||||
/public/
|
||||
/resources/_gen/
|
||||
/assets/jsconfig.json
|
||||
hugo_stats.json
|
6
archetypes/default.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: "{{ replace .Name "-" " " | title }}"
|
||||
date: {{ .Date }}
|
||||
draft: true
|
||||
---
|
||||
|
25
config.toml
Normal file
|
@ -0,0 +1,25 @@
|
|||
baseURL = 'https://janw.name/'
|
||||
languageCode = 'en-us'
|
||||
title = 'janw.name'
|
||||
theme = 'janw'
|
||||
|
||||
[params]
|
||||
subtitle = 'Personal Blog and Portfolio of Jan Wolff'
|
||||
|
||||
[menu]
|
||||
[[menu.main]]
|
||||
name = 'Home'
|
||||
url = '/'
|
||||
weight = 1
|
||||
[[menu.main]]
|
||||
name = 'Blog'
|
||||
url = '/posts/'
|
||||
weight = 100
|
||||
[[menu.main]]
|
||||
name = 'About Me'
|
||||
url = '/about/'
|
||||
weight = 110
|
||||
[[menu.main]]
|
||||
name = 'Projects'
|
||||
url = '/projects/'
|
||||
weight = 120
|
7
content/_index.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: "Home"
|
||||
date: 2022-10-01T18:46:54Z
|
||||
draft: true
|
||||
---
|
||||
|
||||
Hi! I’m Jan (he/him). You can find some of the stuff that I made on this website!
|
6
content/about/_index.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: "About"
|
||||
date: 2022-10-01T19:00:12Z
|
||||
draft: true
|
||||
---
|
||||
|
66
content/legal/_index.md
Normal file
|
@ -0,0 +1,66 @@
|
|||
---
|
||||
title: "Legal Disclaimer"
|
||||
date: 2022-10-08T17:02:00Z
|
||||
draft: true
|
||||
---
|
||||
|
||||
## Disclaimer
|
||||
|
||||
I don't feel comfortable handing out my full address here. Please just send
|
||||
a mail `contact (at) jancc (point) de` and we can discuss anything.
|
||||
|
||||
### Limitation of liability for internal content
|
||||
|
||||
The content of our website has been compiled with meticulous care and to the
|
||||
best of our knowledge. However, we cannot assume any liability for the
|
||||
up-to-dateness, completeness or accuracy of any of the pages.
|
||||
|
||||
Pursuant to section 7, para. 1 of the TMG (Telemediengesetz – Tele Media Act by
|
||||
German law), we as service providers are liable for our own content on these
|
||||
pages in accordance with general laws. However, pursuant to sections 8 to 10 of
|
||||
the TMG, we as service providers are not under obligation to monitor external
|
||||
information provided or stored on our website. Once we have become aware of a
|
||||
specific infringement of the law, we will immediately remove the content in
|
||||
question. Any liability concerning this matter can only be assumed from the
|
||||
point in time at which the infringement becomes known to us.
|
||||
|
||||
### Limitation of liability for external links
|
||||
|
||||
Our website contains links to the websites of third parties („external links“).
|
||||
As the content of these websites is not under our control, we cannot assume any
|
||||
liability for such external content. In all cases, the provider of information
|
||||
of the linked websites is liable for the content and accuracy of the
|
||||
information provided. At the point in time when the links were placed, no
|
||||
infringements of the law were recognisable to us. As soon as an infringement of
|
||||
the law becomes known to us, we will immediately remove the link in question.
|
||||
|
||||
### Copyright
|
||||
|
||||
The content and works published on this website are governed by the copyright
|
||||
laws of Germany. Any duplication, processing, distribution or any form of
|
||||
utilisation beyond the scope of copyright law shall require the prior written
|
||||
consent of the author or authors in question.
|
||||
|
||||
### Data protection
|
||||
|
||||
A visit to our website can result in the storage on our server of information
|
||||
about the access (date, time, page accessed). This does not represent any
|
||||
analysis of personal data (e.g., name, address or e-mail address). If personal
|
||||
data are collected, this only occurs – to the extent possible – with the prior
|
||||
consent of the user of the website. Any forwarding of the data to third parties
|
||||
without the express consent of the user shall not take place.
|
||||
|
||||
We would like to expressly point out that the transmission of data via the
|
||||
Internet (e.g., by e-mail) can offer security vulnerabilities. It is therefore
|
||||
impossible to safeguard the data completely against access by third parties. We
|
||||
cannot assume any liability for damages arising as a result of such security
|
||||
vulnerabilities.
|
||||
|
||||
The use by third parties of all published contact details for the purpose of
|
||||
advertising is expressly excluded. We reserve the right to take legal steps in
|
||||
the case of the unsolicited sending of advertising information; e.g., by means
|
||||
of spam mail.
|
||||
|
||||
Source:
|
||||
[Mustervorlage.net](http://www.mustervorlage.net/disclaimer-muster#Englisch)
|
||||
|
32
content/posts/1-tmpfs-downloads.md
Normal file
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
title: "Ephemeral Downloads"
|
||||
date: 2019-09-19T09:27:04Z
|
||||
draft: true
|
||||
---
|
||||
|
||||
This is just a quick tipp. I added the following line to my `/etc/fstab` file:
|
||||
|
||||
tmpfs /home/jan/Downloads tmpfs rw,nodev,noexec,size=1G 0 0
|
||||
|
||||
It mounts my downloads directory onto an in-memory filesystem. This effectively
|
||||
makes my downloads only stay in RAM. I had the problem in the past that this
|
||||
directory would balloon in size because I'd never clean it. Now it will always
|
||||
be cleaned on reboot because RAM can't hold data without being powered.
|
||||
|
||||
It has some other useful side effects too. As you may noticed there are some
|
||||
other flags added to the mount. `nodev` is obvious. `noexec` makes it
|
||||
impossible to execute anything in this folder. When I'm downloading binaries
|
||||
in order to execute them I want to force myself into moving them somewhere else
|
||||
first. Also while writing this... `nosuid` is kinda redundant now, isn't it? Oh
|
||||
well.
|
||||
|
||||
The size is limited to a single gigabyte. Larger files should likely be
|
||||
archived somewhere else directly, because I don't want to download those
|
||||
multiple times. Is is no problem, by the way, to overprovision the mount's
|
||||
size. It does not reserve the full size on memory, but it grows dynamically.
|
||||
Therefore you could extend this idea onto many more mountpoints.
|
||||
|
||||
Theoretically this is also a great solution should your net-connection be
|
||||
faster than your hard drive's write speed. But I live in Germany so this isn't
|
||||
something I'd need to ever worry about lol.
|
||||
|
220
content/posts/2-wireguard.md
Normal file
|
@ -0,0 +1,220 @@
|
|||
---
|
||||
title: "Setting up a WireGuard VPN"
|
||||
date: 2021-09-28T17:53:09Z
|
||||
draft: true
|
||||
---
|
||||
|
||||
In this post I want to give a quick rundown of the few steps required to use
|
||||
[WireGuard](https://www.wireguard.com/) as a VPN. My setup uses a Raspberry Pi
|
||||
running [Arch Linux ARM](https://archlinuxarm.org/) as the main gateway into my
|
||||
home network. I'll configure another peer such that it can connect to the Pi
|
||||
and thus other devices in my network. The setup is IPv4-only at the moment
|
||||
because my ISP sucks. Also you should have some prior knowledge in networking.
|
||||
|
||||
## First steps
|
||||
|
||||
As ArchLinux ARM (in its default configuration) ships with a Linux kernel with
|
||||
WireGuard support enabled, the first step is to install WireGuard's userland
|
||||
tools.
|
||||
|
||||
$ pacman -S wireguard-tools
|
||||
|
||||
Naturally the package is not called `wireguard-tools` on every platform. A
|
||||
complete list of packages for different operating systems can be found
|
||||
[here](https://www.wireguard.com/install/). This gives you access to the `wg`
|
||||
utility, which can perform several management tasks and the `wg-quick` utility,
|
||||
which can load and apply configurations from files. I'll not be making much use
|
||||
of in-place configuration and instead jump directly into writing configuration
|
||||
files, as they are pretty straightforward regardless. All configuration files
|
||||
live in `/etc/wireguard`. They could be located anywhere but this path allows
|
||||
shorthand notation in `wg-quick` arguments.
|
||||
|
||||
### Server
|
||||
|
||||
First let's set up the server (i.e. the Raspberry Pi), which the client can
|
||||
then connect with in order to have a tunneled connection into my home network.
|
||||
Create a configuration file in `/etc/wireguard/` called `wg0.conf`. Set its
|
||||
mode to `0600` because it will contain a private key and therefore shouldn't be
|
||||
world-readable. The configuration syntax is somewhat similar to Windows' INI
|
||||
files. The server's interface is configured like this:
|
||||
|
||||
[Interface]
|
||||
Address = 192.168.42.1/24
|
||||
ListenPort = 50040
|
||||
PrivateKey = RG9udCB1c2UgdGhpcyB2YWx1ZSB5b3UgZHVtYmFzcyE=
|
||||
MTU = 1420
|
||||
|
||||
`Address` refers to the server's address within the WireGuard tunnel. In my
|
||||
setup I wanted to have the WireGuard "network" live under the netmask
|
||||
`192.168.42.0/24`. Having the main gateway be `192.168.42.1` makes things
|
||||
simple to understand. `ListenPort` is `50040` but can be anything of course
|
||||
(I'm not even sure there is a definite default yet). Setting `MTU` to `1420` is
|
||||
the default and should work pretty much everywhere. Most interesting is the
|
||||
`PrivateKey` field. WireGuard uses Ed25519 keys for authentication and this is
|
||||
simply the server's identity. The value can be generated via `wg genkey`.
|
||||
|
||||
And that's is on the server side for now. You can call `wg-quick up wg0` to
|
||||
enable this interface right now and verify its existence via the output of `ip
|
||||
link` and `ip address` commands.
|
||||
|
||||
### Client
|
||||
|
||||
Now for the same on the client.
|
||||
|
||||
[Interface]
|
||||
Address = 192.168.42.2/24
|
||||
ListenPort = 50041
|
||||
PrivateKey = TmV2ZXIgZXZlciBjb3B5IGtleXMgZnJvbSBndWlkZXM=
|
||||
MTU = 1420
|
||||
|
||||
No surprises here. The client also has a private key and its IP is to be
|
||||
`192.168.42.2`. The `ListenPort` should be different to the server's port, as
|
||||
WireGuard should be able to establish connections in both directions.
|
||||
|
||||
### Peering
|
||||
|
||||
Now we'll connect client and server. To make this work we'll need to exchange
|
||||
keys, as the server needs to know the client's public key and vice versa. The
|
||||
command `wg pubkey` can be used to derive the public key from the private key.
|
||||
For example, to get the server's public key:
|
||||
|
||||
$ echo "RG9udCB1c2UgdGhpcyB2YWx1ZSB5b3UgZHVtYmFzcyE=" | wg pubkey
|
||||
QXJlIHlvdSByZWFkaW5nIHRoaXM/IEZvciByZWFsPyA=
|
||||
|
||||
(Sidenote: This will write the private key into your shell history. So you may
|
||||
want to write the key into a file instead and `cat` it's contents into `wg
|
||||
pubkey`)
|
||||
|
||||
While not strictly required, you may also generate and exchange a _pre-shared
|
||||
key_ between the peers, such that you also benefit from a layer of symmetric
|
||||
cryptography in case you want to harden against quantum cryptanalysis. Such
|
||||
a key can be generated via `wg genpsk`:
|
||||
|
||||
$ wg genpsk
|
||||
eW91IGNvdWxkIGFjdHVhbGx5IHVzZSB0aGlzIG9uZSA=
|
||||
|
||||
Both the client's and the server's configuration needs an additional `[Peer]`
|
||||
section now.
|
||||
|
||||
For the server this section needs to look like this:
|
||||
|
||||
[Peer]
|
||||
PublicKey = a2V5c21hc2hrZXlzbWFzaGtleXNtYXNoa2V5c21hc2g=
|
||||
PresharedKey = eW91IGNvdWxkIGFjdHVhbGx5IHVzZSB0aGlzIG9uZSA=
|
||||
AllowedIPs = 192.168.42.2/32
|
||||
|
||||
And for the client like this:
|
||||
|
||||
[Peer]
|
||||
PublicKey = QXJlIHlvdSByZWFkaW5nIHRoaXM/IEZvciByZWFsPyA=
|
||||
PresharedKey = eW91IGNvdWxkIGFjdHVhbGx5IHVzZSB0aGlzIG9uZSA=
|
||||
AllowedIPs = 192.168.42.1/32
|
||||
Endpoint = vpn-host.example:50040
|
||||
|
||||
Notice the additional `Endpoint` value in the client. This is because the
|
||||
client obviously needs to know where the server is located such that a
|
||||
WireGuard tunnel can be established. This does not need to be a domain name and
|
||||
could instead just be a raw IP address. Of course, in a VPN setup there is no
|
||||
way we could know an `Endpoint` value for the client. The server will learn the
|
||||
client's endpoint after each handshake, which is implicitly performed whenever
|
||||
the client starts to send data to the server.
|
||||
|
||||
...aaand that's it! Do `wg-quick up wg0` on both devices and try to perform a
|
||||
ping over the WireGuard tunnel. You can inspect the state of the tunnel via:
|
||||
|
||||
$ wg
|
||||
|
||||
## VPN
|
||||
|
||||
Our devices can now talk to _each other_ over WireGuard. But that is not
|
||||
enough, as the aim is to allow routing traffic into my home network. I don't
|
||||
care about routing connections to the internet over WireGuard and simply want
|
||||
my client to be able to access devices on the `192.168.0.0/24` network (i.e. my
|
||||
home network).
|
||||
|
||||
We're way more than halfway there. The last two puzzle pieces are: IP
|
||||
forwarding, routing and having traffic from the client to `192.168.0.0/24` move
|
||||
through WireGuard.
|
||||
|
||||
### IP Forwarding
|
||||
|
||||
On Linux, routing can be enabled through `sysctl`:
|
||||
|
||||
$ sysctl -w net.ipv4.ip_forward=1
|
||||
|
||||
To make this setting stick at boot, write this setting into a file in the
|
||||
directory `/etc/sysctl.d`:
|
||||
|
||||
$ echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/ip-forwarding.conf
|
||||
|
||||
### Routing
|
||||
|
||||
Routing, or to be more precise _masquerading_, can be enabled via `iptables`:
|
||||
|
||||
$ iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
|
||||
|
||||
`eth0` needs to be replaced with the canonical name of your server's network
|
||||
interface.
|
||||
|
||||
This can also be automated via WireGuard's configuration manager, which is able
|
||||
to execute commands when an interface is enabled and disabled. Add the command
|
||||
into the `PostUp` option in the `[Interface]` section:
|
||||
|
||||
[Interface]
|
||||
(...)
|
||||
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
|
||||
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
|
||||
|
||||
`PostDown` removes this when the WireGuard interface is disabled.
|
||||
|
||||
### Traffic to 192.168.0.0/24
|
||||
|
||||
This is added to the client's configuration. Remember the `AllowedIPs` key in
|
||||
the `[Peer]` section? You can simply add the whole network like this:
|
||||
|
||||
[Peer]
|
||||
(...)
|
||||
AllowedIPs = 192.168.42.1/32, 192.168.0.0/24
|
||||
|
||||
That's it. `wg-quick` will set up the routes accordingly.
|
||||
|
||||
## And?
|
||||
|
||||
That's it. You're done. Enjoy your VPN :)
|
||||
|
||||
## Persistent Keepalive
|
||||
|
||||
This is a small update after a few months of very successfully using WireGuard.
|
||||
You might find yourself in the following situation: Consider that you have two
|
||||
devices, _A_ and _B_, on your network. _A_ has the address `192.168.42.2` and
|
||||
_B_ has the address `192.168.42.3`. Your router and gateway is at
|
||||
`192.168.42.1`. `wg-quick` sets routing up for you, simply sending all traffic
|
||||
towards `192.168.42.0/24` over your router. Sure you _could_ configure a direct
|
||||
connection between each and every peer manually, but this would get super
|
||||
annoying super fast.
|
||||
|
||||
Device A might be... whatever. And device B might be some gizmo that you only
|
||||
boot up sporadically via Wake-on-LAN. You'll find that, once B is booted up, A
|
||||
has no idea how to talk to B. The router doesn't know that B is awake yet. And
|
||||
B never had any reason to communicate with the router. So the router won't have
|
||||
any clue how to route A's traffic to B. Remember how WireGuard is advertised as
|
||||
not being a talky protocol by default? This is exactly that principle in action
|
||||
and in most cases its perfectly fine. However here it falls flat on its face.
|
||||
What we need to do here, is make sure that the router always knows how to talk
|
||||
to B and that it maintains a route.
|
||||
|
||||
For this end, we can simply add the following line to _B_'s `wg.conf`:
|
||||
|
||||
[Peer]
|
||||
(...)
|
||||
PersistentKeepalive = 30
|
||||
|
||||
Now B will say "hello" to the router every 30 seconds, thus allowing the router
|
||||
to know of B's existence. You can, of course, also choose a higher interval.
|
||||
Most important is the initial handshake from B to the router right after B has
|
||||
finished booting up.
|
||||
|
||||
And this concludes one of the few cases in which you should add
|
||||
`PersistentKeepalive` to your WireGuard configurations. Seriously, if you
|
||||
don't encounter any issues just leave it out.
|
||||
|
113
content/posts/3-msys2-dlls.md
Normal file
|
@ -0,0 +1,113 @@
|
|||
---
|
||||
title: "Collecting the DLLs Required by an MSYS2 Binary"
|
||||
date: 2022-04-21T09:27:15Z
|
||||
draft: true
|
||||
---
|
||||
|
||||
After many unsuccessful attempts of writing a third blog post, I just wanted to
|
||||
use this opportunity to share something useful I found after dabbling with
|
||||
porting an _SDL2_ app to _Windows_ via _MSYS2 MinGW x64_.
|
||||
|
||||
TL;DR: You can collect all the _MinGW_ DLLs your EXE file needs like this:
|
||||
|
||||
ldd my-cool-program.exe | grep /mingw64 | awk '{print $3}' | xargs -i cp {} .
|
||||
|
||||
You see, in the magical Linux realm you'll never really worry about shipping
|
||||
programs in binary form. A nice tarball with a well documented build system is
|
||||
often regarded as good enough. If your program is actually used by people, its
|
||||
likely that distributions pick it up into their repositories. Or you use stuff
|
||||
like _Flatpak_ or _AppImage_ if you want to provide binaries yourself. But
|
||||
over in Windows-land providing .exe files is a normal part of distributing your
|
||||
programs.
|
||||
|
||||
Now, if you use any special libraries they are often dynamically linked and
|
||||
their code is stored externally to your .exe as a .dll. Some .dll files are
|
||||
simply stored somewhere in System32 and are thus available everywhere, but
|
||||
others have to be shipped manually alongside your program.
|
||||
|
||||
---
|
||||
|
||||
Now let me go over a short tangent praising the efforts the developers of
|
||||
_MinGW64_ have made. I wrote a little game in C using Lua and SDL2. On Linux,
|
||||
building that game was simple. I'd use GNU/Make, _pkg-config_ and my distro's
|
||||
package manager to collect the dependencies and tie everything together. I'd
|
||||
dreaded the Windows port but eventually gave it a shot. And holy shit. _MSYS2_
|
||||
provides EXACTLY THE SAME workflow!
|
||||
|
||||
The packages' names are a bit more arcane sounding (e.g.:
|
||||
`mingw-w64-x86_64-gcc`, `mingw-w64-x86_64-SDL2`, `mingw-w64-x86_64-lua`),
|
||||
because MSYS2 provides multiple toolchains and thus the packages have to be
|
||||
more explicit in their naming. But after installing everything and running
|
||||
`make` I had a working .exe file! Well... It was working after I fixed a
|
||||
segfault that I didn't catch under Linux anyways. But that one's on me.
|
||||
|
||||
Running the .exe in MSYS2's shell worked fine, but starting it outside of the
|
||||
shell resulted in most DLLs being unavailable. That's because, all non-system
|
||||
DLLs are not provided to the program by default. That includes stuff like Lua's
|
||||
or SDL2's DLL files. They are stored in the path `/mingw64/bin/`. Now, you
|
||||
COULD go ahead and manually copy them, but why do that when that task can be
|
||||
automated?
|
||||
|
||||
---
|
||||
|
||||
MinGW64 provides a version of the `ldd` program, which spits out all the
|
||||
dynamically linked libraries required by a program. Its output may look
|
||||
something like this:
|
||||
|
||||
$ ldd my-cool-game.exe
|
||||
ntdll.dll => /c/Windows/SYSTEM32/ntdll.dll (0x7ffa09e30000)
|
||||
KERNEL32.DLL => /c/Windows/System32/KERNEL32.DLL (0x7ffa09d30000)
|
||||
KERNELBASE.dll => /c/Windows/System32/KERNELBASE.dll (0x7ffa075f0000)
|
||||
msvcrt.dll => /c/Windows/System32/msvcrt.dll (0x7ffa08c00000)
|
||||
SHELL32.dll => /c/Windows/System32/SHELL32.dll (0x7ffa08cb0000)
|
||||
msvcp_win.dll => /c/Windows/System32/msvcp_win.dll (0x7ffa07550000)
|
||||
ucrtbase.dll => /c/Windows/System32/ucrtbase.dll (0x7ffa07d90000)
|
||||
USER32.dll => /c/Windows/System32/USER32.dll (0x7ffa09690000)
|
||||
win32u.dll => /c/Windows/System32/win32u.dll (0x7ffa07d60000)
|
||||
GDI32.dll => /c/Windows/System32/GDI32.dll (0x7ffa08a50000)
|
||||
gdi32full.dll => /c/Windows/System32/gdi32full.dll (0x7ffa078c0000)
|
||||
SDL2_mixer.dll => /mingw64/bin/SDL2_mixer.dll (0x7ff9f7fd0000)
|
||||
lua54.dll => /mingw64/bin/lua54.dll (0x7ff9f0e80000)
|
||||
libwinpthread-1.dll => /mingw64/bin/libwinpthread-1.dll (0x7ff9f7210000)
|
||||
SDL2.dll => /mingw64/bin/SDL2.dll (0x7ff9e39f0000)
|
||||
(...)
|
||||
|
||||
Most referenced DLLs reside in Window's System32 folder. They are provided by
|
||||
the system and will always be there. So you don't have to worry about providing
|
||||
them. The DLLs in `/mingw64/bin/...` however need to be placed alongside your
|
||||
.exe file if people should be able to run your game via double-clicking it.
|
||||
|
||||
Cool, so that's where our automation can begin! First step is super simple:
|
||||
let's filter out the non-system DLLs using `grep`:
|
||||
|
||||
ldd my-cool-program.exe | grep /mingw64
|
||||
|
||||
Might not be _super_ robust, but I _highly_ doubt that the string "/mingw64"
|
||||
will ever show up in a Windows system DLL's path.
|
||||
|
||||
Next, we only care about the DLL's path. So we use `awk` to cut out that
|
||||
portion of the lines. If we regard the spaces as delimiting characters of text
|
||||
columns, the full path is in the third column (The first is just the filename,
|
||||
and the second is "=>"). The `awk` command `awk {print $3}` gives us this third
|
||||
column, so we can just append it to our shell command:
|
||||
|
||||
ldd my-cool-program.exe | grep /mingw64 | awk '{print $3}'
|
||||
|
||||
By now, our shell command spits our a list of full paths of all non-system DLLs
|
||||
dynamically linked to our program. Cool! But we want to automate the whole
|
||||
thing, so lets add a final call to `xargs`, to copy all files in this list into
|
||||
our current directory. Here, I'll use `xargs -i cp {} .`. The `-i cp {} .`
|
||||
parameter means that, for every file in the list, we call `cp`, pass the DLL's
|
||||
path as the first parameter and the target directory `.` as the second
|
||||
parameter.
|
||||
|
||||
Here is the final call:
|
||||
|
||||
ldd my-cool-program.exe | grep /mingw64 | awk '{print $3}' | xargs -i cp {} .
|
||||
|
||||
---
|
||||
|
||||
Cool! Now go put this in your CI script and automate packaging your Windows
|
||||
releases. Or, if you're like me, make exactly one release and wonder why you
|
||||
spent so much time on figuring this out when you could have just collected the
|
||||
files manually once and then forget about it ARGH
|
5
content/posts/_index.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: "Blog"
|
||||
date: 2022-10-01T18:55:23Z
|
||||
draft: true
|
||||
---
|
6
content/projects/500m.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: "500m"
|
||||
date: 2022-10-08T17:21:27Z
|
||||
draft: true
|
||||
---
|
||||
|
7
content/projects/_index.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: "Projects"
|
||||
date: 2022-10-01T19:00:22Z
|
||||
draft: true
|
||||
---
|
||||
|
||||
Things I've made.
|
6
content/projects/adarkdawn.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: "A Dark Dawn"
|
||||
date: 2022-10-08T17:21:31Z
|
||||
draft: true
|
||||
---
|
||||
|
8
content/projects/antismokeman.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
title: "Anti-Smoke Man"
|
||||
date: 2011-04-01T08:33:34Z
|
||||
teaser: /projects/besmart/screenshot104.png
|
||||
draft: true
|
||||
---
|
||||
|
||||
lol
|
6
content/projects/cybernator.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: "Cybernator"
|
||||
date: 2022-10-08T17:21:11Z
|
||||
draft: true
|
||||
---
|
||||
|
6
content/projects/deathtyper.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: "Death Typer"
|
||||
date: 2022-10-08T17:21:46Z
|
||||
draft: true
|
||||
---
|
||||
|
6
content/projects/duckalypse.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: "Duckalypse"
|
||||
date: 2022-10-08T17:21:18Z
|
||||
draft: true
|
||||
---
|
||||
|
8
content/projects/godscythe.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
title: "Godscythe"
|
||||
date: 2020-02-29T08:33:34Z
|
||||
teaser: /projects/godscythe/godscythe0.jpg
|
||||
draft: true
|
||||
---
|
||||
|
||||
lol
|
7
content/projects/lost.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: "Lost Projects"
|
||||
date: 2022-10-08T17:22:31Z
|
||||
teaser: /projects/pics/house_of_doom.png
|
||||
draft: true
|
||||
---
|
||||
|
6
content/projects/outereartharena.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: "Outer Earth Arena"
|
||||
date: 2022-10-08T17:22:00Z
|
||||
draft: true
|
||||
---
|
||||
|
7
content/projects/raumrace.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: "Raum Race"
|
||||
date: 2022-10-08T17:22:15Z
|
||||
teaser: /projects/raum_race/screenshot101.png
|
||||
draft: true
|
||||
---
|
||||
|
10
layouts/partials/footer.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
<footer class="big-container">
|
||||
<p>
|
||||
Copyright 2013-{{ now.Year }} Jan Wolff. All trademarks and trademarked contents are the properties of their respective owners.
|
||||
All other content, except where noted, is licensed under a
|
||||
<a href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.
|
||||
</p>
|
||||
<p>
|
||||
Refer to the <a href="/legal">legal disclaimer</a> for more information.
|
||||
</p>
|
||||
</footer>
|
BIN
static/projects/besmart/screenshot100-mini.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
static/projects/besmart/screenshot100.png
Executable file
After Width: | Height: | Size: 15 KiB |
BIN
static/projects/besmart/screenshot101-mini.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
static/projects/besmart/screenshot101.png
Executable file
After Width: | Height: | Size: 20 KiB |
BIN
static/projects/besmart/screenshot102-mini.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
static/projects/besmart/screenshot102.png
Executable file
After Width: | Height: | Size: 16 KiB |
BIN
static/projects/besmart/screenshot103-mini.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
static/projects/besmart/screenshot103.png
Executable file
After Width: | Height: | Size: 9.6 KiB |
BIN
static/projects/besmart/screenshot104-mini.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
static/projects/besmart/screenshot104.png
Executable file
After Width: | Height: | Size: 212 KiB |
BIN
static/projects/besmart/screenshot105-mini.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
static/projects/besmart/screenshot105.png
Executable file
After Width: | Height: | Size: 10 KiB |
BIN
static/projects/godscythe/godscythe0-tiny.jpg
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
static/projects/godscythe/godscythe0.jpg
Normal file
After Width: | Height: | Size: 1.1 MiB |
BIN
static/projects/godscythe/godscythe1-tiny.jpg
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
static/projects/godscythe/godscythe1.jpg
Normal file
After Width: | Height: | Size: 920 KiB |
BIN
static/projects/godscythe/godscythe10-tiny.jpg
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
static/projects/godscythe/godscythe10.jpg
Normal file
After Width: | Height: | Size: 914 KiB |
BIN
static/projects/godscythe/godscythe11-tiny.jpg
Normal file
After Width: | Height: | Size: 7 KiB |
BIN
static/projects/godscythe/godscythe11.jpg
Normal file
After Width: | Height: | Size: 697 KiB |
BIN
static/projects/godscythe/godscythe12-tiny.jpg
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
static/projects/godscythe/godscythe12.jpg
Normal file
After Width: | Height: | Size: 462 KiB |
BIN
static/projects/godscythe/godscythe13-tiny.jpg
Normal file
After Width: | Height: | Size: 9.3 KiB |
BIN
static/projects/godscythe/godscythe13.jpg
Normal file
After Width: | Height: | Size: 791 KiB |
BIN
static/projects/godscythe/godscythe14-tiny.jpg
Normal file
After Width: | Height: | Size: 9.4 KiB |
BIN
static/projects/godscythe/godscythe14.jpg
Normal file
After Width: | Height: | Size: 764 KiB |
BIN
static/projects/godscythe/godscythe15-tiny.jpg
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
static/projects/godscythe/godscythe15.jpg
Normal file
After Width: | Height: | Size: 888 KiB |
BIN
static/projects/godscythe/godscythe16-tiny.jpg
Normal file
After Width: | Height: | Size: 6.5 KiB |
BIN
static/projects/godscythe/godscythe16.jpg
Normal file
After Width: | Height: | Size: 611 KiB |
BIN
static/projects/godscythe/godscythe17-tiny.jpg
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
static/projects/godscythe/godscythe17.jpg
Normal file
After Width: | Height: | Size: 460 KiB |
BIN
static/projects/godscythe/godscythe18-tiny.jpg
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
static/projects/godscythe/godscythe18.jpg
Normal file
After Width: | Height: | Size: 748 KiB |
BIN
static/projects/godscythe/godscythe19-tiny.jpg
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
static/projects/godscythe/godscythe19.jpg
Normal file
After Width: | Height: | Size: 800 KiB |
BIN
static/projects/godscythe/godscythe2-tiny.jpg
Normal file
After Width: | Height: | Size: 5.4 KiB |
BIN
static/projects/godscythe/godscythe2.jpg
Normal file
After Width: | Height: | Size: 378 KiB |
BIN
static/projects/godscythe/godscythe20-tiny.jpg
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
static/projects/godscythe/godscythe20.jpg
Normal file
After Width: | Height: | Size: 636 KiB |
BIN
static/projects/godscythe/godscythe21-tiny.jpg
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
static/projects/godscythe/godscythe21.jpg
Normal file
After Width: | Height: | Size: 840 KiB |
BIN
static/projects/godscythe/godscythe3-tiny.jpg
Normal file
After Width: | Height: | Size: 9.6 KiB |
BIN
static/projects/godscythe/godscythe3.jpg
Normal file
After Width: | Height: | Size: 1 MiB |
BIN
static/projects/godscythe/godscythe4-tiny.jpg
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
static/projects/godscythe/godscythe4.jpg
Normal file
After Width: | Height: | Size: 795 KiB |
BIN
static/projects/godscythe/godscythe5-tiny.jpg
Normal file
After Width: | Height: | Size: 8.3 KiB |
BIN
static/projects/godscythe/godscythe5.jpg
Normal file
After Width: | Height: | Size: 756 KiB |
BIN
static/projects/godscythe/godscythe6-tiny.jpg
Normal file
After Width: | Height: | Size: 9.4 KiB |
BIN
static/projects/godscythe/godscythe6.jpg
Normal file
After Width: | Height: | Size: 910 KiB |
BIN
static/projects/godscythe/godscythe7-tiny.jpg
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
static/projects/godscythe/godscythe7.jpg
Normal file
After Width: | Height: | Size: 880 KiB |
BIN
static/projects/godscythe/godscythe8-tiny.jpg
Normal file
After Width: | Height: | Size: 9.3 KiB |
BIN
static/projects/godscythe/godscythe8.jpg
Normal file
After Width: | Height: | Size: 652 KiB |
BIN
static/projects/godscythe/godscythe9-tiny.jpg
Normal file
After Width: | Height: | Size: 8 KiB |
BIN
static/projects/godscythe/godscythe9.jpg
Normal file
After Width: | Height: | Size: 706 KiB |
BIN
static/projects/godscythe/logo.png
Normal file
After Width: | Height: | Size: 73 KiB |
30
static/projects/godscythe/trailer.html
Normal file
|
@ -0,0 +1,30 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Godscythe Trailer</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
video {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
min-width: 100%;
|
||||
min-height: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<video controls>
|
||||
<source src="trailer.webm" type="video/webm">
|
||||
<source src="movie.mp4" type="video/mp4">
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
</body>
|
||||
</html>
|
BIN
static/projects/godscythe/trailer.mp4
Normal file
BIN
static/projects/godscythe/trailer.webm
Normal file
BIN
static/projects/pics/cue-mini.jpg
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
static/projects/pics/cue.png
Normal file
After Width: | Height: | Size: 1,018 KiB |
BIN
static/projects/pics/cue2-mini.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
static/projects/pics/cue2.png
Normal file
After Width: | Height: | Size: 552 KiB |
BIN
static/projects/pics/house_of_doom-mini.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
static/projects/pics/house_of_doom.png
Normal file
After Width: | Height: | Size: 1.3 MiB |
BIN
static/projects/pics/intermission-mini.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
static/projects/pics/intermission.png
Normal file
After Width: | Height: | Size: 382 KiB |
BIN
static/projects/pics/intermission_basement-mini.png
Normal file
After Width: | Height: | Size: 45 KiB |
BIN
static/projects/pics/intermission_basement.png
Normal file
After Width: | Height: | Size: 1.6 MiB |
BIN
static/projects/pics/intermission_fields-mini.png
Normal file
After Width: | Height: | Size: 49 KiB |
BIN
static/projects/pics/intermission_fields.png
Normal file
After Width: | Height: | Size: 1.4 MiB |
BIN
static/projects/pics/intermission_menu-mini.png
Normal file
After Width: | Height: | Size: 49 KiB |
BIN
static/projects/pics/intermission_menu.png
Normal file
After Width: | Height: | Size: 632 KiB |
BIN
static/projects/raum_race/screenshot100-mini.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
static/projects/raum_race/screenshot100.png
Executable file
After Width: | Height: | Size: 10 KiB |
BIN
static/projects/raum_race/screenshot101-mini.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
static/projects/raum_race/screenshot101.png
Executable file
After Width: | Height: | Size: 12 KiB |