initial commit

This commit is contained in:
Michael Clemens 2021-07-14 01:53:07 +02:00
commit ac2914e923
102 changed files with 1971 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
public/*

12
.gitmodules vendored Normal file
View File

@ -0,0 +1,12 @@
[submodule "themes/hugo-coder"]
path = themes/hugo-coder
url = https://github.com/luizdepra/hugo-coder.git
[submodule "themes/hugo-theme-cactus"]
path = themes/hugo-theme-cactus
url = https://github.com/monkeyWzr/hugo-theme-cactus.git
[submodule "themes/cactus"]
path = themes/cactus
url = https://github.com/monkeyWzr/hugo-theme-cactus.git
[submodule "themes/smol"]
path = themes/smol
url = https://github.com/colorchestra/smol

4
README.md Normal file
View File

@ -0,0 +1,4 @@
Source of my personal website: https://clemens.name
* Static site generator: Hugo (https://gohugo.io/)
* Theme: hugo-coder (https://github.com/luizdepra/hugo-coder/)

0
archetypes/.gitkeep Normal file
View File

6
archetypes/default.md Normal file
View File

@ -0,0 +1,6 @@
---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
draft: true
---

47
config.toml Normal file
View File

@ -0,0 +1,47 @@
baseURL = "https://qrz.is/"
languageCode = "en-us"
title = "Michael Clemens"
theme = "smol"
publishDir = "/var/www/qrz.is"
# Menu links
[menu]
[[menu.main]]
name = "Posts"
weight = 1
url = "/post/"
[[menu.main]]
name = "Projects"
weight = 3
url = "/projects/"
[[menu.main]]
name = "About"
weight = 4
url = "/about/"
[[menu.footer]]
name = "Github"
weight = 5
url = "https://github.com/exitnode/"
[[menu.footer]]
name = "Mastodon"
weight = 6
url = "https://mastodon.radio/@DL6MHC"
[[menu.footer]]
name = "QRZ"
weight = 7
url = "https://qrz.com/DB/DL6MHC"
[[menu.footer]]
name = "Datenschutz"
weight = 8
url = "/privacy/"
[[menu.footer]]
name = "Impressum"
weight = 9
url = "/impressum/"
dateFormat = "2006-01-02" # default
copyright = "Michael Clemens"

0
content/.gitkeep Normal file
View File

0
content/_index.md Normal file
View File

25
content/about.md Normal file
View File

@ -0,0 +1,25 @@
---
title: "About"
slug: "about"
date: 2018-05-03T16:42:59+02:00
draft: false
---
Hi, I'm Michael Clemens. I'm an information security engineer with many years of experience in information technology. My first computer was a Commodore C64 (1989), followed by an Amiga (1992) and finally, in 1995, I got my first PC. In 1998 I installed my first Linux distribution (S.u.S.E. Linux 5.3), moved to Debian in 2002, tried a lot of BSDs and Linux distributions but always came back to Debian.
I support the [Free Software Foundation Europe (fsfe.org)][1]. Everything I code in my freetime is therefore published as open source software. If you are interested, you can have a look at my projects [here][2]. I also try to document interesting stuff on my [blog][4].
Besides that, I enjoy gaming on everything 8-bit (C64, Atari 2600, NES etc.) or fantasy consoles (PICO-8, TIC-80).
Apart from computer related hobbies, I love analog photography, bicycles, reading and many more.
I am a licensed ham radio operator and member of the [DARC][3]. My callsign is DL6MHC. You can find some information about my station on my [QRZ.com page][6].
If you'd like to contact me, please send me a mail to mail@_domainofthiswebsite_ or send me a toot on [Mastodon][5].
[1]: https://wiki.fsfe.org/Fellows/clemens
[2]: /projects/
[3]: https://www.darc.de
[4]: /blog/
[5]: https://mastodon.radio/@DL6MHC
[6]: https://qrz.com/DB/DL6MHC

41
content/impressum.md Normal file
View File

@ -0,0 +1,41 @@
---
title: "Impressum"
slug: "impressum"
date: 2018-05-03T16:42:59+02:00
draft: false
---
Michael Clemens
c/o Block Services
Stuttgarter Str. 106
70736 Fellbach
Telefon: 0162/3522778
E-Mail: [impressum_0x7E5@qrz.is](mailto:impressum_0x7E5@qrz.is)
**Verantwortlich für den Inhalt** (gem. § 55 Abs. 2 RStV):
Michael Clemens
c/o Block Services
Stuttgarter Str. 106
70736 Fellbach
## Disclaimer rechtliche Hinweise
### § 1 Warnhinweis zu Inhalten
Die kostenlosen und frei zugänglichen Inhalte dieser Webseite wurden mit größtmöglicher Sorgfalt erstellt. Der Anbieter dieser Webseite übernimmt jedoch keine Gewähr für die Richtigkeit und Aktualität der bereitgestellten kostenlosen und frei zugänglichen journalistischen Ratgeber und Nachrichten. Namentlich gekennzeichnete Beiträge geben die Meinung des jeweiligen Autors und nicht immer die Meinung des Anbieters wieder. Allein durch den Aufruf der kostenlosen und frei zugänglichen Inhalte kommt keinerlei Vertragsverhältnis zwischen dem Nutzer und dem Anbieter zustande, insoweit fehlt es am Rechtsbindungswillen des Anbieters.
### § 2 Externe Links
Diese Website enthält Verknüpfungen zu Websites Dritter ("externe Links"). Diese Websites unterliegen der Haftung der jeweiligen Betreiber. Der Anbieter hat bei der erstmaligen Verknüpfung der externen Links die fremden Inhalte daraufhin überprüft, ob etwaige Rechtsverstöße bestehen. Zu dem Zeitpunkt waren keine Rechtsverstöße ersichtlich. Der Anbieter hat keinerlei Einfluss auf die aktuelle und zukünftige Gestaltung und auf die Inhalte der verknüpften Seiten. Das Setzen von externen Links bedeutet nicht, dass sich der Anbieter die hinter dem Verweis oder Link liegenden Inhalte zu Eigen macht. Eine ständige Kontrolle der externen Links ist für den Anbieter ohne konkrete Hinweise auf Rechtsverstöße nicht zumutbar. Bei Kenntnis von Rechtsverstößen werden jedoch derartige externe Links unverzüglich gelöscht.
### § 3 Urheber- und Leistungsschutzrechte
Die auf dieser Website veröffentlichten Inhalte unterliegen dem deutschen Urheber- und Leistungsschutzrecht. Jede vom deutschen Urheber- und Leistungsschutzrecht nicht zugelassene Verwertung bedarf der vorherigen schriftlichen Zustimmung des Anbieters oder jeweiligen Rechteinhabers. Dies gilt insbesondere für Vervielfältigung, Bearbeitung, Übersetzung, Einspeicherung, Verarbeitung bzw. Wiedergabe von Inhalten in Datenbanken oder anderen elektronischen Medien und Systemen. Inhalte und Rechte Dritter sind dabei als solche gekennzeichnet. Die unerlaubte Vervielfältigung oder Weitergabe einzelner Inhalte oder kompletter Seiten ist nicht gestattet und strafbar. Lediglich die Herstellung von Kopien und Downloads für den persönlichen, privaten und nicht kommerziellen Gebrauch ist erlaubt.
Die Darstellung dieser Website in fremden Frames ist nur mit schriftlicher Erlaubnis zulässig.
### § 4 Besondere Nutzungsbedingungen
Soweit besondere Bedingungen für einzelne Nutzungen dieser Website von den vorgenannten Paragraphen abweichen, wird an entsprechender Stelle ausdrücklich darauf hingewiesen. In diesem Falle gelten im jeweiligen Einzelfall die besonderen Nutzungsbedingungen.
Quelle: [Hier aufrufen](https://www.juraforum.de)

View File

@ -0,0 +1,61 @@
---
title: The Laundruino
date: 2011-08-05T09:58:52+00:00
url: /the-arduino-enabled-washing-machine/
categories:
- arduino
tags:
- arduino
---
My washing machine is located in the basement. Unfortunately, the time data displayed on the front panel is always inaccurate. So instead of constantly running down the stairs and checking if the laundry is done, I decided to connect the washing machine to my LAN and extend it’s features by a simple http server. This is what I needed for it:
* 1 [arduino uno][1]
* 1 [ethernet shield][2]
* 1 opto-coupler (CNY17)
* 1 perfboard
* 1 resistor (150 Ohm)
In my case, getting the right signal from the washing machine was simple: It has a „Finished“ LED on the front panel, so all I needed to do, was to solder it out and replace it with a two-core wire.
![image][3]
![image][4]
![image][5]
To connect my washing machine with the arduino, I built a minimal shield with a prefboard and a CNY17. Here’s how everything is put together:
![image][6]
![image][7]
![image][8]
Now I have a LOW signal on pin A2 (digital mode) when the laundry is done and a HIGH signal if the machine is running or turned off. In my case, a loop of 100ms duration is needed every time to watch the signal because I don’t get a steady voltage here (I guess the front panel LEDs might be multiplexed). If  the signal becomes LOW once in this time window, the washing machine has finished and the LED would have turned on.
![image][9]
Screenshots:
![image][10]
![image][11]
You can download the code on github: [https://github.com/exitnode/laundruino ][12]
 
[1]: http://arduino.cc/en/Main/ArduinoBoardUno
[2]: http://arduino.cc/en/Main/ArduinoBoardEthernet
[3]: /img/laundruino1_panel_small.jpg
[4]: /img/laundruino2_cuircuit_board_small.jpg
[5]: /img/laundruino3_washer_small.jpg
[6]: /img/laundruino4_schematics_small.jpg
[7]: /img/laundruino5_shield_small.jpg
[8]: /img/laundruino6_shield_small.jpg
[9]: /img/laundruino7_debug_small.jpg
[10]: /img/laundruino8_screen1.jpg
[11]: /img/laundruino9_screen2.jpg
[12]: https://github.com/exitnode/laundruino

View File

@ -0,0 +1,130 @@
---
title: The One Button Audiobook Player
author: micha
date: 2012-10-29T23:20:05+00:00
url: /the-one-button-audiobook-player/
categories:
- Uncategorized
tags:
- raspberry audiobook
---
This little Raspberry Pi based project is a gift for my wife’s grandmother for her 90th birthday. Being visually impaired, she is hard to entertain but loves to listen to audiobooks. The problem is, that she isn’t able to handle a ghetto blaster or MP3 player.
The solution to this problem was – tadaaaah – a one button audiobook player 🙂
It basically consists of:
* 1 Raspberry Pi
* 1 [ModMyPi enclosure][1]
* 1 button
* 2 resistors (330 Ohm, 10 Kilo-Ohm)
* 1 blue LED
* 1 (slow) 8GB SD-Card
* some wire
* a pair of speakers
The following software has been used:
* Raspbian minimal image ([http://www.linuxsystems.it/2012/06/raspbian-wheezy-armhf-raspberry-pi-minimal-image][2])
* mpd (music player daemon)
* mpc
* mpd-python
* pyudev (for USB access)
* a self-written python script
The features are the following:
* **always on:** When you power on the raspberry, it will boot up and start the python script with the audio book in pause
* **one button usage:** The button pauses and unpauses the audio book or goes back one track when you press the button longer than 4 seconds
* **remembers position:** It will always remember the last played position
* **only one audiobook:** There will always be only one audio book on the Raspberry
* **easy audio book deployment:** When you plug in a USB thumb drive with a special name/label, the Raspberry will stop playing, mount the thumb drive, deletes the old audio book, copies the new one, rebuilds the playlist and – after unplugging the thumb drive – starts the new audiobook in pause mode
* **multi format:** Since it uses mpd, the player supports  Ogg Vorbis, FLAC, OggFLAC, MP2, MP3, MP4/AAC, MOD, Musepack and wave
Some pics and a video:
![image][3]
![image][4]
<iframe frameborder="0" width="525" height="295" src="https://www.dailymotion.com/embed/video/xup7rg" allowfullscreen allow="autoplay"></iframe>
(The audiobook used in this video is a free version of Cory Doctorows &#8222;Little Brother&#8220; from <a href="http://www.mokita.de/" target="_blank">Fabian Neidhardt</a>)
If you like to build your own one button audio book player, here are the super simple schematics:
![image][5]
And last but not least &#8211; the python script. The code might be crappy, please comment if you have improvements (especially regarding loadMusic). You can find it on github:
<https://github.com/exitnode/theonebuttonaudiobookplayer>
**Update (2013-11-26)**
Here&#8217;s what Russel wrote in a comment to this post:
I just completed building this and have some addendum notes adding more details:
Install the following packages:
sudo apt-get install mpd
sudo apt-get install mpc
sudo apt-get install python-mpd
sudo apt-get install python-pyudev
(below assumes using defaults for /etc/mpd.conf)
sudo mkdir -p /music/usb
sudo ln -s /var/lib/mpd /music/mpd
sudo ln -s /var/lib/mpd/music /music/mp3
Copy the tobabp.py script to /home/pi
nano /home/pi/tobabp.py
Change these in the script or flip the connections in wiring diagram.
BUTTON = 17
LED = 24
Testing
Rename a USB stick to “1GB”
Copy 1 MP3 onto the stick
Insert the stick into pi
sudo mount /dev/sda1 /music/usb
sudo /etc/init.d/mpd stop
sudo rm /music/mp3/*
sudo cp /music/usb/* /music/mp3/
sudo umount /music/usb
Remove the USB stick
sudo rm /music/mpd/tag_cache
sudo /etc/init.d/mpd start
mpc clear
mpc ls
mpc ls | mpc add
sudo /etc/init.d/mpd restart
mpc play
Plug in earphones
You should hear audio
Next try the python script:
sudo python /home/pi/tobabp.py
Insert USB stick
the LED should flash and the USB file copy to /music/mp3/
the LED should flash again. Remove the Stick and LED flashes again.
Press button to start playing
Press button again to stop
Press & hold button to rewind to beginning.
sudo crontab -e
Add following line run at startup
@reboot python /home/pi/tobabp.py &
sudo reboot
Then retest again to be sure all is well.
[1]: https://www.modmypi.com/
[2]: http://www.linuxsystems.it/2012/06/raspbian-wheezy-armhf-raspberry-pi-minimal-image/
[3]: /img/obabp_1.jpg
[4]: /img/obabp_2.jpg
[5]: /img/obabp_schematics.jpg

View File

@ -0,0 +1,25 @@
---
title: Adressenmeister
author: micha
date: 2013-01-29T12:39:02+00:00
url: /adressenmeister/
categories:
- Uncategorized
---
I&#8217;d like to share my very first software project from 1992 with you which was written in BASIC 2.0 on my C64. It has never really been finished but had a nice intro screen with moving sprites and was able to print labels on a wire printer 🙂
In order to archive it for myself, I&#8217;ve set up a github repository where the source code is available: [https://github.com/exitnode/adressenmeister][1]
Here&#8217;s a little screen-cap of it:
<iframe frameborder="0" width="525" height="371" src="https://www.dailymotion.com/embed/video/xx3xfk" allowfullscreen allow="autoplay"></iframe>
Update:
Here&#8217;s a pic of the floppy disk:
![image][2]
[1]: https://github.com/exitnode/adressenmeister "https://github.com/exitnode/adressenmeister"
[2]: /img/diskette.jpg

View File

@ -0,0 +1,25 @@
---
title: Little Helper
author: micha
date: 2013-03-23T11:49:38+00:00
url: /little-helper/
categories:
- Uncategorized
---
Here&#8217;s the result of my attempt to recreate [Gyro Gearloose&#8217;s Little Helper (in German: Daniel Düsentrieb&#8217;s Helferlein)][1]:
![image][2]
It&#8217;s built out of:
* aluminium tubes
* brass sticks
* wooden shoes and gloves
* lots of two-component adhesive
* a 12V 40W bulb with E27 thread
* some wire
* a AC/DC converter 12V 3A
[1]: https://www.duckipedia.de/Helferlein
[2]: /img/helferlein_final_small.jpg

View File

@ -0,0 +1,21 @@
---
title: One-button audiobook player features in new book
author: micha
date: 2013-05-03T13:16:03+00:00
url: /one-button-audiobook-player-features-in-new-book/
categories:
- Uncategorized
---
The One-button audiobook player has been included in the new book Raspberry Pi For Dummies by Sean McManus and Mike Cook. The book covers setting up the Raspberry Pi, using Linux on it, using the Pi for work and play, programming the Raspberry Pi in Scratch and Python, and creating electronics projects.
![image][1]
Co-author Sean McManus told me: “We wanted to finish the book by highlighting some inspiring projects that would give people an idea of what they could do by taking their new programming and electronics skills further. The one-button audiobook player is a nice example of an electronics project, but I particularly like the way its really improving someones quality of life, by making it possible for your wifes grandmother to listen to audiobooks. I get a lot of enjoyment from audiobooks myself, so I can imagine how much it means to her to be able to listen to them, especially given her visual impairment.”
Other inspiring Raspberry Pi projects mentioned in the book include a synthesiser, a bird feeder webcam, a weather station and a jukebox.
You can [find out more about Raspberry Pi For Dummies at Seans website][2].
[1]: /img/rapidcover250.jpg
[2]: http://www.sean.co.uk/books/raspberry-pi-for-dummies/index.shtm

View File

@ -0,0 +1,22 @@
---
title: 'NSE-Script: SQLite output for Nmap'
author: micha
date: 2014-05-05T13:36:29+00:00
url: /nse-script-sqlite-output-for-nmap/
categories:
- Uncategorized
---
I wrote this little NSE script that allows you to store the output of Nmap into a SQLite database: <a href="https://github.com/exitnode/nmap-sqlite-output" title="sqlite-output" target="_blank">https://github.com/exitnode/nmap-sqlite-output<br /> </a>
This might come in handy when performing large inventory scans. The SQLite database can be queried and sorted easily or exported as a CSV file. This way you can, for example, easily generate tables for your assessment report.
**Example:**
`$ nmap -sS -A -F --script sqlite-output scanme.nmap.org<br />
[...]<br />
$ sqlite3 scan.sqlite<br />
[...]<br />
sqlite> select * from scandata;<br />
scanme.nmap.org|74.207.244.221|22|tcp|ssh|open|OpenSSH5.3p1 Debian 3ubuntu7.1<br />
scanme.nmap.org|74.207.244.221|80|tcp|http|open|Apache httpd2.2.14`

View File

@ -0,0 +1,14 @@
---
title: Patch for the CLI password manager „pass“
author: micha
date: 2016-05-25T21:47:20+00:00
url: /patch-for-the-cli-password-manager-pass/
categories:
- Uncategorized
---
I use Pass (https://www.passwordstore.org/) to store and synchronize all my passwords.
When I use Pass via SSH on a remote system in order to retrieve a password, I cannot make use of it&#8217;s clipboard feature. In order to output the password without actually displaying it, I wrote the following patch which prints the password in red on a red background while still being able to be manually copied to the clipboard:
<https://gist.github.com/exitnode/73065c7ecf3c2e5bb77cef5a8563b86e>

View File

@ -0,0 +1,20 @@
---
title: Correlation Rule Documentation Generator for McAfee SIEM
author: micha
date: 2018-04-29T13:09:57+00:00
url: /correlation-rule-documentation-generator-for-mcafee-siem/
categories:
- Uncategorized
---
Since we are required to document all custom correlation rules inside our SIEM (McAfee Enterprise Security Manager) for our customers, I wrote a Python script that converts XML rule exports to Markdown. Afterwards its easy to convert teh resulting file e.g. to PDF, DOCX, HTML or even variuous wiki-formats with e.g. Pandoc. This way it&#8217;s possible to generate a PDF documentation of all rules with just a few clicks/commands.
![image][1]
On the long shot that this is useful for you, you can find the script on [Github][2].
Please comment on this on the [McAfee Support Community][3] or on [Github][2].
[1]: /img/esm2markdown.png
[2]: https://github.com/exitnode/esm2markdown "Github"
[3]: https://community.mcafee.com/t5/Security-Information-and-Event/Script-Automatic-Correlation-Rule-Documentation-Generator/m-p/590048

View File

@ -0,0 +1,103 @@
---
title: Dynamic DNS for NSD
author: micha
date: 2018-05-03T02:26:11+00:00
url: /dynamic-dns-for-nsd/
categories:
- Uncategorized
---
# Introduction
nsd-dyndns is a simple script that adds dynamic DNS dunctionality to NSD (authoritative DNS name server).
# Requirements
The following is required or suggested:
* OpenBSD (or another BSD or some Linux distro) with HTTPD and NSD installed (pkg_add nsd), configured and running
* (sub-)domain for your webserver. Needed for updating the NS record of your actual DynDNS domain.
* In this example: _update.example.com_
* (sub-)domain that is updated dynamically.
* In this example: _dyn.example.com_
* A router capable of sending custom GET-requests to your DynDNS server.
* In this example: A FritzBox
# Installation
## Configure your HTTPD
Add the following new virtual host to your _/etc/httpd.conf_:
server "update.example.com" {
listen on $ext_addr port 80
root "/htdocs/dyndns"
log access dyndns.log
}
Create an empty _update.html_:
# mkdir /var/www/htdocs/dyndns/
# touch /var/www/htdocs/dyndns/update.html
After reloading HTTPD, try to access <a href="http://update.example.com/update.html" rel="nofollow">http://update.example.com/update.html</a> The request should show up in _/var/www/logs/dyndns.log_
## **Create a zone file for dyn.example.com**
Create a new zone file (e.g. at _/var/nsd/zones/dyn.example.com.zone_) with the following content
$ORIGIN example.com.
$TTL 300
@ IN SOA ns1.example.com. admin.example.com. (
1524952218
300 ; refresh
900 ; retry
1209600 ; expire
1800 ; ttl
)
; Name servers
IN NS ns1.example.com.
IN NS ns1.example.com.
; A records
@ IN A 123.123.123.123
update IN A 123.123.123.123
dyn IN A 123.123.123.123
Don&#8217;t forget to set your own domain names, name servers and ip addresses Furthermore, add this zone file to your _/var/nsd/etc/nsd.conf_
## Configure and Install nsd-dyndns
* Download the scripts from here: https://github.com/exitnode/nsd-dyndns
* Copy _dyndns.conf-dist_ to _/etc/dyndns.conf_
* _\# cp dyndns.conf-dist /etc/dyndns.conf_
* Edit _/etc/dyndns.conf_ to your needs
* Copy _dyndns.sh_ to _/usr/local/bin/dyndns.sh_
* _\# cp dyndns.sh /usr/local/bin/dyndns.sh_
* Make the script executable:
* _\# chmod u+x /usr/local/bin/dyndns.sh_
* Add _/usr/local/bin/dyndns.sh_ to your crontab
## Configure your router
Configure your router to query the following URL:
http://update.example.com/update.html?qwertzuiop1234567890
Don&#8217;t forgert to set your own domain name and to replace the string after &#8222;?&#8220; with the password you configured in the config file.
# What it does
When your router gets a new IP and therefore sends an HTTP request to your server, a similar entry should appear in your _/var/www/logs/dyndns.log_:
update.example.com 123.123.123.123 - - [29/Apr/2018:20:48:19 +0200] "GET /update.html?qwertzuiop1234567890 HTTP/1.1" 200 6
When the script is executed e.g. via cron, the following happens:
* It greps the last line of _/var/www/logs/dyndns.log_ where the correct password was found and extracts the requesting IP address
* It checks if this IP is the same than the last time
* If it&#8217;s a new IP, then it replaces the forth line in your zone file &#8211; the line with the version number &#8211; with a new version (current unix time stamp)
* As a second step, it updates the A record of you DynDNS domain (dyn.example.com in our example)
* It then stores the new IP in the file _/tmp/last\_dyndns\_ip.txt_
* Finally it reloads NSD

View File

@ -0,0 +1,52 @@
---
title: "Shortened 30m Dipole"
date: 2020-02-02T15:00:00+02:00
url: /30m-dipole/
---
# Why and what
This aricle describes the construction of a 9,50 m long dipole for the 30 m band (10.1 MHz to 10.15 MHz). It was designed to be mounted ca. 6m above ground inside an attic. The calculations were performed by OE1MEW with the help of [this antenna calculator](http://66pacific.com). To reduce the length of the ~15 m long dipole, a coil will be integrated into each side of the dipole.
The following diagram shows the dipole in theory:
![image][1]
# Bill of materials
* 1 feed point connector with PL socket or a 1:1 balun
* 2 isolators
* 2x 1 m antenna wire
* 2x ca. 4 m antenna wire
* 2 short pieces of 16 mm installation tubes
* several meters of 1.5 mm2 copper wire (e.g. out of NYM-J 3 x 1,5 cable)
# Construction
## Coils
Drill a hole into the 16 mm installation tube and stick a few centimeters of the 1.5 mm2 wire through it. Afterwards tightly wind the wire around it 37 times. After the 37th turn, drill a hole closely to the wire into the tube and stick the wire through it. It now should look like this:
![image][2]
Repeat this step to build a second coil.
## Assembly
Connect 1 m antenna wire to each side of the feed point connector (or the 1:1 balun). Now solder the ends of the antenna wires to one side of each coil. Use shrink tubing to make it water resistant. Solder the 4 m pieces of antenna wire to the other side of the coils. Both ends should then be terminated with isolatiors. A good start for tuning is a wire length of about 3,60 m between coil and isolator. Wrap around the remaining 40 cm for the tuning procedure.
The result should look like this:
![image][3]
# Result
The antenna ended up being 9,30 m long (including feed point, excluding isolators). The following photos show how nicely this antenna can be tuned:
![image][4]
[1]: /img/30m_dipole_schematics.jpg
[2]: /img/30m_dipole_coil.jpg
[3]: /img/30m_dipole.jpg
[4]: /img/30m_dipole_nanovna.jpg

22
content/post/cif.md Normal file
View File

@ -0,0 +1,22 @@
---
title: "Cif / Bearded Avenger"
date: 2018-10-28T20:09:18+01:00
draft: true
---
# Introduction
cif@cif:~$ cif --itype fqdn --tags malware --limit 1 --fields tlp,indicator,count,tags,description,confidence,rdata,provider
+-------+----------------+-------+---------+----------------+------------+-------+--------------+
| tlp | indicator | count | tags | description | confidence | rdata | provider |
+-------+----------------+-------+---------+----------------+------------+-------+--------------+
| white | erxxxxxxzq.com | 2 | malware | malware domain | 9.0 | None | spamhaus.org |
+-------+----------------+-------+---------+----------------+------------+-------+--------------+
cif@cif:~$ cif --indicator 2xx.xx.xx.xx7 --format table --fields tlp,indicator,count,tags,description,confidence,rdata,provider --limit 3
+-------+---------------+-------+--------------------+------------------+------------+-------+---------------------+
| tlp | indicator | count | tags | description | confidence | rdata | provider |
+-------+---------------+-------+--------------------+------------------+------------+-------+---------------------+
| green | 2xx.xx.xx.xx7 | 1 | malware | compromised host | 8.0 | None | emergingthreats.net |
| green | 2xx.xx.xx.xx7 | 6 | bruteforce,scanner | None | 9.0 | None | dataplane.org |
| amber | 2xx.xx.xx.xx7 | 7 | search | None | 10.0 | None | admin |
+-------+---------------+-------+--------------------+------------------+------------+-------+---------------------+

60
content/post/g90-mods.md Normal file
View File

@ -0,0 +1,60 @@
---
title: "Xiegu G90 Mods"
author: micha
date: 2020-01-17T15:00:00+02:00
url: /g90-mods/
---
# Mods
The following is a compilation of some recommended mods for the Xiegu G90. None of these mods are my idea, I learned about them from the Xiegu G90 group.io group (see below).
## Power Cable
The original power cable is too thin and should be replaced with silicone 14AWG cables plus some ferrite beads. Don't forget to integrate a 5Ah fuse into the cable.
Mine looks like this now:
![image][1]
## Microphone Mod
When using the original G90 microphone, your voice might be too bassy. To solve this problem, open the mic and replace the cpacitor C15 with a 10 nanofarad SMD capacitor and C14 with 2,2 nanofarad (both size 0603). [source](https://xiegug90.groups.io/g/main/profile/@YO2AA)
The following image shows both capacitors (taken from https://xiegug90.groups.io/g/main/message/1219):
![image][2]
## Ferrite Beads
In order to prevent radio-frequency interference, all cables should be fitted with ferrite beads:
* Microphone cable
* Power cord
* CAT cable
* Head unit connection cable
## VFO Knob
Not essential but nice: A larger VFO knob. I bought a black aluminium potentiometer knob for 6mm axis with a size of 32x13mm.
The G90 with a larger VFO knob:
![image][3]
## Head Unit Stand
I like [this 3D printable design over at thingiverse.com](https://www.thingiverse.com/thing:3741359) for placing the head unit on the table in an ergonomic way.
# Useful other Information
* Very active and helpful community: [XieguG90](https://xiegug90.groups.io/g/main)
* [G90 Update Instructions](https://xiegug90.groups.io/g/main/files/G90%20Firmware%20Update%20Instructions/G90%20Firmware%20Update%20Instructions.pdf)
* [CI-V Reference](https://xiegug90.groups.io/g/main/files/G90%20CI-V%20REFERENCE.pdf)
* [Cheat Sheet](https://xiegug90.groups.io/g/main/files/XIEGU%20G90%20CHEAT%20SHEET%20v1.73%2012-15-2019.pdf)
* [ini file for OnmiRig](https://xiegug90.groups.io/g/main/files/XieguG90.ini)
[1]: /img/g90_power_cable.jpg
[2]: /img/g90_mic_mod.jpg
[3]: /img/g90_vfo_knob.jpg

View File

@ -0,0 +1,46 @@
---
title: "Heated Trackball"
date: 2014-12-22T14:34:34+02:00
draft: false
---
## Parts needed
* Heating wire (0,2mm 43,95 Ohm/m Kanthal D)
* some regular wire
* glue
* soldering equipment
Since the USB port should ghive us 500mAh and the trackball shouldn't
consume more than 150mAh, the wire might consume 350mAh. Knowing the
voltage of 5V and the desired power consumption, it is easy to
calculate the needed resistor:
![image][1]
The heating wire has a resistance of 43,95 Ohm per meter, the wire
needs to be 33cm long in order to consume 350mAh:
Icalculation of the wire length /pics/length.png
## Assembly
Glueing the wire to the inner side of the housing:
![image][2]
After reassembling the mouse buttons:
![image][3]
The finished trackball:
![image][4]
![image][5]
[1]: /img/resistance.png
[2]: /img/trackball1.jpg
[3]: /img/trackball3.jpg
[4]: /img/trackball2.jpg
[5]: /img/trackball4.jpg

View File

@ -0,0 +1,77 @@
---
title: "MikroTik: Auto-Backup der Routerkonfiguration via FTP"
author: micha
date: 2019-01-04T22:00:11+02:00
url: /blog/mikrotik-auto-backup/
draft: false
categories:
- MikroTik
---
# Einführung
Folgend wird beschrieben, wie man seinen MikroTik Router automatisch sichert und das Backup auf einen FTP-Server überträgt. Zielsetzung ist die folgende:
* Erstellung eines Exports und eines Backups
* Speicherung des letzten Backups/Exports auf dem Router selbst
* Übertragung der Dateien auf einen FTP-Server
# Vorbedingungen
* MikroTik RouterBoard, z.B. ein MikroTik hEX
* FTP-Server im LAN
# Quellen
* [Mikrotik Forum Post von rextended](https://forum.mikrotik.com/viewtopic.php?t=87749#p440665)
* [https://github.com/massimo-filippi/mikrotik/blob/master/backup-config.rsc](https://github.com/massimo-filippi/mikrotik/blob/master/backup-config.rsc)
# Los geht's
## Skript
## environment specific configuration
:local ftpServer "1.2.3.4"
:local ftpUser "user"
:local ftpPassword "pass"
:local ftpPath "/"
:local dstFile "backup"
:local srcFile $dstFile
:local myVer value=[/system package update get installed-version];
:local id value=[/system identity get value-name=name];
:local date value=[/system clock get date];
## replace "/" with "-" in date
:local newdate value="";
:if ([:find $date "/" -1] > 0) do={
:for i from=0 to=([:len $date] -1) step=1 do={
:local actualchar value=[:pick $date $i];
:if ($actualchar = "/") do={ :set actualchar value="-" };
:set newdate value=($newdate.$actualchar);
}
};
## construct destination file name
:set dstFile ($dstFile . "-" . $id . "-" . $myVer . "-" . $newdate);
## perform the actual backup / export
/system backup save name="$srcFile"
/export file="$srcFile"
## upload both files via FTP
:foreach i in=(".backup", ".rsc") do={
/tool fetch address=$ftpServer src-path=($srcFile . $i) user=$ftpUser mode=ftp password=$ftpPassword dst-path=($ftpPath . $dstFile . $i) upload=yes port=21
}
## Log
:log info ("Configuration backup created on router $[/system identity get name].")
## Scheduler
Nachdem das Skript unter dem Namen "backup-config" angelegt wurde, kann man es mit folgendem Befehl täglich um 3:00 Uhr ausführen lassen:
/system scheduler
add interval=1d name=backup-config on-event=backup-config start-date=jan/05/2019 start-time=03:00:00

View File

@ -0,0 +1,97 @@
---
title: "MikroTik: Zentrales WiFi-Management mit CAPsMAN"
author: micha
date: 2018-12-31T16:00:11+02:00
url: /blog/mikrotik-capsman-setup/
draft: false
categories:
- MikroTik
---
# Einführung
Folgend wird beschrieben, wie man mit CAPsMAN beliebig viele Wireless Access Points verwaltet und dynamisch provisioniert. Zielsetzung ist die folgende:
* Zentrale Verwaltung aller APs im Haus (zunächst 3 APs, weitere sollen jederzeit ohne Aufwand hinzugefügt werden können)
* 2 SSIDs, je eine SSID für 2,4 GHz und eine für 5 GHz
* Jeder AP soll die gleiche Konfiguration erhalten
* Umgebung soll beliebig erweiterbar sein, z.B. weitere SSID mit eigenem VLAN
# Vorbedingungen
* MikroTik RouterBoard mit installiertem "wireless" Package, z.B. ein MikroTik hEX
* 1-n MikroTik Wireless Access Points, z.B. wAP AC
# CAPsMAN konfigurieren
## Channels
Zu Beginn definieren wir zwei Channels:
/caps-man channel
add band=2ghz-g/n control-channel-width=20mhz extension-channel=disabled frequency=2437 name="2.4 GHz"
add band=5ghz-n/ac name="5 GHz"
Hierbei ist folgendes zu beachten:
* 2.4 GHz WLANs sollten idealerweise die Kanäle 1, 6 oder 11 nutzen. CAPsMAN verlangt die Angabe der jeweiligen Trägerfrequenz, diese kann [hier](https://www.elektronik-kompendium.de/sites/net/1712061.htm) nachgeschaut werden (hier 2437 MHz = Kanal 6).
* Bei einem Frequenzbereich von 2.4 GHz ist eine Kanalbreite von 20 MHz ideal
* Auf 802.11g sollte man unbedingt verzichten, da dies die Gesamtgeschwindigkeit reduziert und sowieso keine g-Clients zu erwarten sein sollten.
## Security Configurations
In meiner Umgebung verwende ich das gleiche Passwort für beide SSIDs:
/caps-man security
add authentication-types=wpa2-psk disable-pmkid=yes encryption=aes-ccm group-encryption=aes-ccm group-key-update=1h name="Wifi Security Settings" passphrase=GeheimesPasswort
Hierbei ist folgendes zu beachten:
* Auf WPA kann man in den meisten fällen verzichten, WPA2 ist immer zu bevorzugen
* Mit "disable-pmkid=yes" mitigiert man die Schwachstelle CVE-2018-3580
## Datapaths
Hier gibt es kaum etwas zu beachten, gegebenenfalls muss anstelle von "bridge1" der Name der Bridge angegeben werden, die auf dem Router definiert wurde:
/caps-man datapath
add bridge=bridge1 client-to-client-forwarding=yes local-forwarding=yes name=BridgeDP
## Configurations
Die bisher definierten Einstellungen werden nun in zwei übergeordneten Konfigurationen eingesetzt. Diese Konfigurationen werden in einem späteren Schritt verwendet, um die APs zu provisionieren:
/caps-man configuration
add channel="2.4 GHz" country=germany datapath=BridgeDP installation=indoor name="2.4 GHz" security="Wifi Security Settings" ssid="Mein WLAN (2.4 GHz)"
add channel="5 GHz" country=germany datapath=BridgeDP name="5 GHz" security="Wifi Security Settings" ssid="Mein WLAN (5 Ghz)"
## Provisioning
Folgende Einstellungen sorgen dafür, dass jeder AP vollständig dynamisch provisioniert wird:
/caps-man provisioning
add action=create-enabled hw-supported-modes=g master-configuration="2.4 GHz" name-format=prefix-identity name-prefix=2.4GHz
add action=create-enabled hw-supported-modes=ac master-configuration="5 GHz" name-format=prefix-identity name-prefix=5GHz
Über den Parameter "hw-supported-modes" wird gesteuert, dass Interfaces, die "g" unterstützen (und es sich somit um 2.4 GHz Interfaces handelt), die Konfiguration "2.4 GHz" erhalten. 5 GHz Interfaces, welche "ac" unterstützen, erhalten wiederum die Konfiguration mit dem Namen "5 GHz".
## Manager
Schlussendlich aktivieren wir den Manager mit
/caps-man manager
set enabled=yes
# Inbetriebnahme
Zu beachten ist, dass man keine CAP Interfaces anlegen muss - dies geschieht vollautomatisch. Jetzt können die neuen APs hinzugefügt werden:
* Während des Einschaltens 10 Sekunden lang Reset gedrückt halten bis die "AP/CAP"-LED anfängt zu blinken (von Modell abhängig)
* Nach einer Weile erscheinen dann pro AP zwei CAP Interfaces mit dem Namensmuster "2.4GHz-MikroTik-1" bzw. "5GHz-MikroTik-1"
* Fertig!
Sinnvolle ToDos:
* Alle APs aktualiseren (Packages + Firmware)
* Jedem AP ein Passwort vergeben
* Jedem AP eine Identity geben, z.B. "AP EG", "AP OG" und "AP Büro" statt "MikroTik"

View File

@ -0,0 +1,61 @@
---
title: "MikroTik: Ausführen von Skripten per SMS"
author: micha
date: 2018-12-30T13:00:11+02:00
url: /blog/mikrotik-exec-scripts-via-sms/
draft: false
categories:
- MikroTik
---
# Einführung
Dieser Blogeintrag beschäftigt sich mit dem Ausführen von Skripten per SMS-Kommandos. In diesem Beispiel soll als Aktion eine SMS zurückgesendet werden, welche die aktuelle öffentliche IP-Adresse enthält.
# Vorbedingungen
* MikroTik RouterBoard mit USB-Port, z.B. ein MikroTik hEX
* USB UMTS-Stick, z.B. ein Standard Huawei Stick aus verschiedenen Prepaid-Angeboten
# Los geht's
Zuerst schauen wir nach, ob der Router den USB-Stick erkannt hat:
[admin@hEX] /system resource usb> print
# DEVICE VENDOR NAME SPEED
0 1-0 Linux 3.3.5 xhci-hcd xHCI Host Controller 480
1 2-0 Linux 3.3.5 xhci-hcd xHCI Host Controller 5000
2 1-1 HUAWEI Technology HUAWEI Mobile 480
Anschließend versenden wir eine Test-SMS:
/tool sms send usb1 "+4915212345678" message="Test"
Nach dem erfolgreichen Test kann das benötigte Skript wie folgt erstellt werden:
/system script
add dont-require-permissions=yes name=extip owner=admin policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\
"/tool fetch url=\"https://icanhazip.com/\" mode=http dst-path=mypublicip.txt\r\
\n:local currentIP [/file get mypublicip.txt contents]\r\
\n:put \$currentIP\r\
\n/tool sms send usb1 \"+4915212345678\" message=\"\$currentIP\";"
Zur Ermittlung der öffentlichen IP wird absichtlich nicht das WAN-Interface abgefragt, sondern ein externer Dienst, da mein Router nicht direkt mit dem Internet verbunden ist. Die Antwort des versendeten GET-Requests wird in der Datei mypublicip.txt zwischengespeichert und direkt darauf per SMS an die im Skript hinterlegte Nummer gesendet.
Zuletzt muss noch der Empfang von SMS aktiviert werden:
/tool sms
set allowed-number=+4915212345678 port=usb1 receive-enabled=yes secret=GeheimesPasswort
Wenn alles geklappt hat, muss man folgenden Text (ohne Anführungszeichen) and die Nummer des UMTS-Sticks senden:
":cmd GeheimesPasswort extip"
Als Antwort sollte anschließend die öffentliche IP-Adresse des Routers kommen.
Weitere Informationen sind dem MikroTik Wiki entnehmbar:
* [Manual:Tools/SMS](https://wiki.mikrotik.com/wiki/Manual:Tools/Sms)
* [Manual:Tools/Fetch](https://wiki.mikrotik.com/wiki/Manual:Tools/Fetch)
* [Manual:Scripting](https://wiki.mikrotik.com/wiki/Manual:Scripting)

42
content/post/qrz-sh.md Normal file
View File

@ -0,0 +1,42 @@
---
title: "qrz.sh - a CLI QRZ.com query tool"
author: micha
date: 2020-11-09T17:00:00+02:00
url: /qrz-sh/
---
# About
This script queries the QRZ.com callsign database and returns
the result to the command line. A XML subscription plan with
QRZ.com is required for full functionality.
You can download the script here: [https://github.com/exitnode/qrz.sh](https://github.com/exitnode/qrz.sh)
![screenshot](/img/qrz-sh.jpg)
# Installation
* Copy the file _.qrz.conf_ into your home directory
* Copy the file _qrz.sh_ into a directory that is in you PATH variable
* Set the correct file permissions: _chmod u+x qrz.sh_
# Dependencies
* curl
# Configuration
Edit the file _~/.qrz.conf_ like this:
```
user=<your QRZ.com username - typically your callsign>
password=<your QRZ.com password - NOT your API key>
```
# Usage
```
# qrz.sh <callsign>
```

View File

@ -0,0 +1,58 @@
---
title: "The AntennaPi"
author: micha
date: 2019-07-05T13:29:09+02:00
url: /the-antennapi/
---
## Parts needed
* Aluminium case
* Raspberry Pi 1 or newer
* relay module
* PL sockets
* screws, cables, etc.
* soldering equipment, drill, etc.
This is a remote antenna switch I use in my attic to connect transceivers
in the basement to multiple antennas in the attic. There is only one antenna
cable going up to the attic which is why an antenna switch is needed.
The goal of this project is to be able to remotely connect one of the
antennas in the attic to the only antenna cable available.
Since I only have two antennas in place at the moment, I only installed
two relays and only wired up two PL sockets. In the future I'll be able
to upgrade easily by adding a second module.
## Hardware
Drill the holes for the PL sockets:
![image][1]
Install the sockets:
![image][2]
Mount the relay module and use some antenna wire to connect the sockets with the relay module like this:
![image][3]
In the end it looks like this:
![image][4]
![image][5]
![image][6]
## Software
[1]: /img/antennapi01.jpg
[2]: /img/antennapi02.jpg
[3]: /img/antennapi03.jpg
[4]: /img/antennapi04.jpg
[5]: /img/antennapi05.jpg
[6]: /img/antennapi06.jpg

99
content/privacy.md Normal file
View File

@ -0,0 +1,99 @@
---
title: "Datenschutzerklärung"
slug: "privacy"
date: 2018-05-03T16:42:59+02:00
draft: false
---
Verantwortlicher im Sinne der Datenschutzgesetze, insbesondere der EU-Datenschutzgrundverordnung (DSGVO), ist:
Michael Clemens
c/o Block Services
Stuttgarter Str. 106
70736 Fellbach
Deutschland
E-Mail-Adresse: datenschutz_0x7E5@qrz.is
Ihre Betroffenenrechte
----------------------
Unter den angegebenen Kontaktdaten unseres Datenschutzbeauftragten können Sie jederzeit folgende Rechte ausüben:
* Auskunft über Ihre bei uns gespeicherten Daten und deren Verarbeitung (Art. 15 DSGVO),
* Berichtigung unrichtiger personenbezogener Daten (Art. 16 DSGVO),
* Löschung Ihrer bei uns gespeicherten Daten (Art. 17 DSGVO),
* Einschränkung der Datenverarbeitung, sofern wir Ihre Daten aufgrund gesetzlicher Pflichten noch nicht löschen dürfen (Art. 18 DSGVO),
* Widerspruch gegen die Verarbeitung Ihrer Daten bei uns (Art. 21 DSGVO) und
* Datenübertragbarkeit, sofern Sie in die Datenverarbeitung eingewilligt haben oder einen Vertrag mit uns abgeschlossen haben (Art. 20 DSGVO).
Sofern Sie uns eine Einwilligung erteilt haben, können Sie diese jederzeit mit Wirkung für die Zukunft widerrufen.
Sie können sich jederzeit mit einer Beschwerde an eine Aufsichtsbehörde wenden, z. B. an die zuständige Aufsichtsbehörde des Bundeslands Ihres Wohnsitzes oder an die für uns als verantwortliche Stelle zuständige Behörde.
Eine Liste der Aufsichtsbehörden (für den nichtöffentlichen Bereich) mit Anschrift finden Sie unter: [https://www.bfdi.bund.de/DE/Service/Anschriften/Laender/Laender-node.html](https://www.bfdi.bund.de/DE/Service/Anschriften/Laender/Laender-node.html).
Erfassung allgemeiner Informationen beim Besuch unserer Website
---------------------------------------------------------------
### Art und Zweck der Verarbeitung:
Wenn Sie auf unsere Website zugreifen, d.h., wenn Sie sich nicht registrieren oder anderweitig Informationen übermitteln, werden automatisch Informationen allgemeiner Natur erfasst. Diese Informationen (Server-Logfiles) beinhalten etwa die Art des Webbrowsers, das verwendete Betriebssystem, den Domainnamen Ihres Internet-Service-Providers, Ihre IP-Adresse und ähnliches.
Sie werden insbesondere zu folgenden Zwecken verarbeitet:
* Sicherstellung eines problemlosen Verbindungsaufbaus der Website,
* Sicherstellung einer reibungslosen Nutzung unserer Website,
* Auswertung der Systemsicherheit und -stabilität sowie
* zur Optimierung unserer Website.
Wir verwenden Ihre Daten nicht, um Rückschlüsse auf Ihre Person zu ziehen. Informationen dieser Art werden von uns ggfs. anonymisiert statistisch ausgewertet, um unseren Internetauftritt und die dahinterstehende Technik zu optimieren.
### Rechtsgrundlage und berechtigtes Interesse:
Die Verarbeitung erfolgt gemäß Art. 6 Abs. 1 lit. f DSGVO auf Basis unseres berechtigten Interesses an der Verbesserung der Stabilität und Funktionalität unserer Website.
### Empfänger:
Empfänger der Daten sind ggf. technische Dienstleister, die für den Betrieb und die Wartung unserer Webseite als Auftragsverarbeiter tätig werden.
### Speicherdauer:
Die Daten werden gelöscht, sobald diese für den Zweck der Erhebung nicht mehr erforderlich sind. Dies ist für die Daten, die der Bereitstellung der Website dienen, grundsätzlich der Fall, wenn die jeweilige Sitzung beendet ist.
### Bereitstellung vorgeschrieben oder erforderlich:
Die Bereitstellung der vorgenannten personenbezogenen Daten ist weder gesetzlich noch vertraglich vorgeschrieben. Ohne die IP-Adresse ist jedoch der Dienst und die Funktionsfähigkeit unserer Website nicht gewährleistet. Zudem können einzelne Dienste und Services nicht verfügbar oder eingeschränkt sein. Aus diesem Grund ist ein Widerspruch ausgeschlossen.
SSL-Verschlüsselung
-------------------
Um die Sicherheit Ihrer Daten bei der Übertragung zu schützen, verwenden wir dem aktuellen Stand der Technik entsprechende Verschlüsselungsverfahren (z. B. SSL) über HTTPS.
* * *
Information über Ihr Widerspruchsrecht nach Art. 21 DSGVO
---------------------------------------------------------
### Einzelfallbezogenes Widerspruchsrecht
Sie haben das Recht, aus Gründen, die sich aus Ihrer besonderen Situation ergeben, jederzeit gegen die Verarbeitung Sie betreffender personenbezogener Daten, die aufgrund Art. 6 Abs. 1 lit. f DSGVO (Datenverarbeitung auf der Grundlage einer Interessenabwägung) erfolgt, Widerspruch einzulegen; dies gilt auch für ein auf diese Bestimmung gestütztes Profiling im Sinne von Art. 4 Nr. 4 DSGVO.
Legen Sie Widerspruch ein, werden wir Ihre personenbezogenen Daten nicht mehr verarbeiten, es sei denn, wir können zwingende schutzwürdige Gründe für die Verarbeitung nachweisen, die Ihre Interessen, Rechte und Freiheiten überwiegen, oder die Verarbeitung dient der Geltendmachung, Ausübung oder Verteidigung von Rechtsansprüchen.
### Empfänger eines Widerspruchs
Michael Clemens
c/o Block Services
Stuttgarter Str. 106
70736 Fellbach
Deutschland
E-Mail-Adresse: datenschutz_0x7E5@qrz.is
* * *
Änderung unserer Datenschutzbestimmungen
----------------------------------------
Wir behalten uns vor, diese Datenschutzerklärung anzupassen, damit sie stets den aktuellen rechtlichen Anforderungen entspricht oder um Änderungen unserer Leistungen in der Datenschutzerklärung umzusetzen, z.B. bei der Einführung neuer Services. Für Ihren erneuten Besuch gilt dann die neue Datenschutzerklärung.
_Die Datenschutzerklärung wurde mithilfe der activeMind AG erstellt, den Experten für [externe Datenschutzbeauftragte](https://www.activemind.de/datenschutz/datenschutzbeauftragter/) (Version #2020-09-30)._

49
content/projects.md Normal file
View File

@ -0,0 +1,49 @@
---
title: "Projects"
date: 2018-05-03T15:42:59+02:00
draft: false
---
#### Software Projects
* [TSM Monitor][1] - A PHP application for monitoring IBM's Tivoli Storage Manager
* [TSM Monitor 2][2] - An enhanced PHP application for monitoring IBM's Tivoli Storage Manager
* [MSTerminology][3] - Translates strings used in all kind of Microsoft products
* [Nmap-sqlite-output][4] - Nmap NSE script for writing the scan output into a sqlite3 database
* [Adressenmeister][5] - Adressenmeister - my very first "software project" (C64 BASIC)
* [Shellfolio][6] - A command line cryptocurrency portfolio manager and price tracker
* [esm2markdown][7] - A converter for McAfee SIEM rule export files to Markdown documents
* [nsd-dyndns][8] - Dynamic DNS for NSD
#### Hardware Projects
* [The Laundruino][9] - Washing machine monitoring with an Arduino
* [The One Button Audio Book Player][10] - The one button audiobook player
* [Little Helper][11] - Daniel Duesentrieb's Little Helper
* [Heated Trackball][14] - Heating mod for Logitech trackballs
#### Amateur Radio
* [The AntennaPi][17] - Raspberry Pi based remote antenna switch
* [Shortened 30m Dipole][18] - Dipole for the 30m band, designed for a 10m long attic
#### Organizations / Projects I like and support
* [Free Software Foundation Europe][15] - a charity that empowers users to control technology.
* [Super Dimension Fortress][16] - SDF Public Access UNIX System .. Est. 1987
[1]: https://github.com/exitnode/tsmmonitor
[2]: https://github.com/exitnode/tsmmonitor2
[3]: https://github.com/exitnode/MSTerminology
[4]: https://github.com/exitnode/nmap-sqlite-output
[5]: https://github.com/exitnode/adressenmeister
[6]: https://github.com/exitnode/shellfolio
[7]: https://github.com/exitnode/esm2markdown
[8]: https://github.com/exitnode/nsd-dyndns
[9]: /the-arduino-enabled-washing-machine/
[10]: /the-one-button-audiobook-player/
[11]: /little-helper/
[12]: https://clemens.name/curses/index.html
[13]: gopher://gopher.bildschirmtext.com
[14]: /blog/heated_trackball/
[15]: http://fsfe.org
[16]: http://sdf.org
[17]: /the-antennapi/
[18]: /30m-dipole/

0
data/.gitkeep Normal file
View File

0
layouts/.gitkeep Normal file
View File

View File

@ -0,0 +1,7 @@
<footer>
<p>&copy; {{ now.Year }} <a href="{{ .Site.BaseURL }}"><b>{{ if .Site.Copyright }}{{ .Site.Copyright }}{{ else }}{{ .Site.Title }}{{ end }}</b></a>
{{- range .Site.Menus.footer }}
/ <a href="{{ .URL }}"><b>{{ .Name }}</b></a>
{{- end }}
</p>
</footer>

View File

@ -0,0 +1,20 @@
<header>
<div class="ascii-art">
██████╗ ██████╗ ███████╗ ██╗ ██████╗
██╔═══██╗██╔══██╗╚════██║ ██║██╔════╝
██║██╗██║██████╔╝ ███╔═╝ ██║╚█████╗
╚██████╔╝██╔══██╗██╔══╝ ██║ ╚═══██╗
╚═██╔═╝ ██║ ██║███████╗██╗██║██████╔╝
╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝╚═╝╚═════╝
</div>
<nav>
--> <a href="/"><b>Home</b></a>
{{ with .Site.Menus.main }}
{{ range . }}
- <a href="{{ .URL | relURL }}"><b>{{ .Name }}</b></a>
{{ end }} <--
</nav>
</p>
{{ end }}
</header>

0
resources/.gitkeep Normal file
View File

View File

@ -0,0 +1 @@
body.colorscheme-dark{color:#dadada;background-color:#212121}body.colorscheme-dark a{color:#36679f}body.colorscheme-dark h1,body.colorscheme-dark h2,body.colorscheme-dark h3,body.colorscheme-dark h4,body.colorscheme-dark h5,body.colorscheme-dark h6{color:#dadada}body.colorscheme-dark code{background-color:#424242;color:#dadada}body.colorscheme-dark pre code{background-color:inherit;color:inherit}body.colorscheme-dark blockquote{border-left:2px solid #424242}body.colorscheme-dark table td,body.colorscheme-dark table th{border:2px solid #dadada}@media(prefers-color-scheme:dark){body.colorscheme-auto{color:#dadada;background-color:#212121}body.colorscheme-auto a{color:#36679f}body.colorscheme-auto h1,body.colorscheme-auto h2,body.colorscheme-auto h3,body.colorscheme-auto h4,body.colorscheme-auto h5,body.colorscheme-auto h6{color:#dadada}body.colorscheme-auto code{background-color:#424242;color:#dadada}body.colorscheme-auto pre code{background-color:inherit;color:inherit}body.colorscheme-auto blockquote{border-left:2px solid #424242}body.colorscheme-auto table td,body.colorscheme-auto table th{border:2px solid #dadada}}body.colorscheme-dark .content .list ul li .title{color:#dadada}body.colorscheme-dark .content .list ul li .title:hover,body.colorscheme-dark .content .list ul li .title:focus{color:#36679f}body.colorscheme-dark .content .centered .about ul li a{color:#dadada}body.colorscheme-dark .content .centered .about ul li a:hover,body.colorscheme-dark .content .centered .about ul li a:focus{color:#36679f}@media(prefers-color-scheme:dark){body.colorscheme-auto .content .list ul li .title{color:#dadada}body.colorscheme-auto .content .list ul li .title:hover,body.colorscheme-auto .content .list ul li .title:focus{color:#36679f}body.colorscheme-auto .content .centered .about ul li a{color:#dadada}body.colorscheme-auto .content .centered .about ul li a:hover,body.colorscheme-auto .content .centered .about ul li a:focus{color:#36679f}}body.colorscheme-dark .navigation a,body.colorscheme-dark .navigation span{color:#dadada}body.colorscheme-dark .navigation a:hover,body.colorscheme-dark .navigation a:focus{color:#36679f}@media only screen and (max-width:768px){body.colorscheme-dark .navigation .navigation-list{background-color:#212121;border-top:solid 2px #424242;border-bottom:solid 2px #424242}}@media only screen and (max-width:768px){body.colorscheme-dark .navigation .navigation-list .menu-separator{border-top:2px solid #dadada}}@media only screen and (max-width:768px){body.colorscheme-dark .navigation #menu-toggle:checked+label{color:#424242}}@media only screen and (max-width:768px){body.colorscheme-dark .navigation .menu-button{color:#dadada}body.colorscheme-dark .navigation .menu-button:hover,body.colorscheme-dark .navigation .menu-button:focus{color:#36679f}}@media(prefers-color-scheme:dark){body.colorscheme-auto .navigation a,body.colorscheme-auto .navigation span{color:#dadada}body.colorscheme-auto .navigation a:hover,body.colorscheme-auto .navigation a:focus{color:#36679f}}@media only screen and (prefers-color-scheme:dark) and (max-width:768px){body.colorscheme-auto .navigation .navigation-list{background-color:#212121;border-top:solid 2px #424242;border-bottom:solid 2px #424242}}@media only screen and (prefers-color-scheme:dark) and (max-width:768px){body.colorscheme-auto .navigation .navigation-list .menu-separator{border-top:2px solid #dadada}}@media only screen and (prefers-color-scheme:dark) and (max-width:768px){body.colorscheme-auto .navigation #menu-toggle:checked+label{color:#424242}}@media only screen and (prefers-color-scheme:dark) and (max-width:768px){body.colorscheme-auto .navigation .menu-button{color:#dadada}body.colorscheme-auto .navigation .menu-button:hover,body.colorscheme-auto .navigation .menu-button:focus{color:#36679f}}body.colorscheme-dark .footer a{color:#36679f}@media(prefers-color-scheme:dark){body.colorscheme-auto .footer a{color:#36679f}}

View File

@ -0,0 +1 @@
{"Target":"css/coder-dark.min.83a2010dac9f59f943b3004cd6c4f230507ad036da635d3621401d42ec4e2835.css","MediaType":"text/css","Data":{"Integrity":"sha256-g6IBDayfWflDswBM1sTyMFB60DbaY102IUAdQuxOKDU="}}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"Target":"css/coder.min.40d8e1c52a909f26a3afa74a018f27732272cd6f868dafd9cca806423a7eee2f.css","MediaType":"text/css","Data":{"Integrity":"sha256-QNjhxSqQnyajr6dKAY8ncyJyzW+Gja/ZzKgGQjp+7i8="}}

View File

@ -0,0 +1,403 @@
*,
*:after,
*:before {
box-sizing: inherit; }
html {
box-sizing: border-box;
font-size: 62.5%; }
body {
color: #212121;
background-color: #FAFAFA;
font-family: Merriweather, Georgia, serif;
font-size: 1.6em;
font-weight: 300;
line-height: 1.8em; }
@media only screen and (max-width: 768px) {
body {
font-size: 1.6em;
line-height: 1.6em; } }
a {
font-weight: 300;
color: #1565c0;
text-decoration: none; }
a:focus, a:hover {
text-decoration: underline; }
p {
margin: 2.0rem 0 2.0rem 0; }
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: Lato, Helvetica, sans-serif;
font-weight: 700;
color: #000;
margin: 6.4rem 0 3.2rem 0; }
h1 {
font-size: 3.2rem;
line-height: 3.6rem; }
@media only screen and (max-width: 768px) {
h1 {
font-size: 3.0rem;
line-height: 3.4rem; } }
h2 {
font-size: 2.8rem;
line-height: 3.2rem; }
@media only screen and (max-width: 768px) {
h2 {
font-size: 2.6rem;
line-height: 3.0rem; } }
h3 {
font-size: 2.4rem;
line-height: 2.8rem; }
@media only screen and (max-width: 768px) {
h3 {
font-size: 2.2rem;
line-height: 2.6rem; } }
h4 {
font-size: 2.2rem;
line-height: 2.6rem; }
@media only screen and (max-width: 768px) {
h4 {
font-size: 2.0rem;
line-height: 2.4rem; } }
h5 {
font-size: 2.0rem;
line-height: 2.4rem; }
@media only screen and (max-width: 768px) {
h5 {
font-size: 1.8rem;
line-height: 2.2rem; } }
h6 {
font-size: 1.8rem;
line-height: 2.2rem; }
@media only screen and (max-width: 768px) {
h6 {
font-size: 1.6rem;
line-height: 2.0rem; } }
b, strong {
font-weight: 700; }
pre {
display: block;
font-family: "Source Code Pro", "Lucida Console", monospace;
font-size: 1.6rem;
font-weight: 400;
line-height: 2.6rem;
margin: 2.0rem 0 2.0rem 0;
padding: 2.0rem;
overflow-x: auto; }
pre code {
display: inline-block;
background-color: inherit;
color: inherit; }
code {
font-family: "Source Code Pro", "Lucida Console", monospace;
font-size: 1.6rem;
font-weight: 400;
background-color: #E0E0E0;
color: #212121;
padding: 0.2rem 0.4rem 0.2rem 0.4rem; }
blockquote {
border-left: 2px solid #E0E0E0;
padding-left: 2.0rem;
line-height: 2.2rem;
font-weight: 400;
font-style: italic; }
th, td {
padding: 1.6rem; }
table {
border-collapse: collapse; }
table td, table th {
border: 2px solid #000; }
table tr:first-child th {
border-top: 0; }
table tr:last-child td {
border-bottom: 0; }
table tr td:first-child,
table tr th:first-child {
border-left: 0; }
table tr td:last-child,
table tr th:last-child {
border-right: 0; }
img {
max-width: 100%; }
.wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%; }
.container {
margin: 0 auto;
max-width: 90.0rem;
width: 100%;
padding-left: 2.0rem;
padding-right: 2.0rem; }
.fab {
font-weight: 400; }
.fas {
font-weight: 700; }
.float-right {
float: right; }
.float-left {
float: left; }
.fab {
font-weight: 400; }
.fas {
font-weight: 900; }
.content {
flex: 1;
display: flex;
margin-top: 1.6rem;
margin-bottom: 3.2rem; }
.content article header {
margin-top: 6.4rem;
margin-bottom: 3.2rem; }
.content article header h1 {
font-size: 4.2rem;
line-height: 4.6rem;
margin: 0; }
@media only screen and (max-width: 768px) {
.content article header h1 {
font-size: 4.0rem;
line-height: 4.4rem; } }
.content article footer {
margin-top: 4.0rem; }
.content .post .post-title {
margin-bottom: .75em; }
.content .post .post-meta i {
text-align: center;
width: 1.6rem;
margin-left: 0;
margin-right: 0.5rem; }
.content .post .post-meta .date .posted-on {
margin-left: 0;
margin-right: 1.5rem; }
.content figure {
margin: 0;
padding: 0; }
.content figcaption p {
text-align: center;
font-style: italic;
font-size: 1.6rem;
margin: 0; }
.avatar img {
width: 20rem;
height: auto;
border-radius: 50%; }
@media only screen and (max-width: 768px) {
.avatar img {
width: 10rem; } }
.list ul {
margin: 3.2rem 0 3.2rem 0;
list-style: none;
padding: 0; }
.list ul li {
font-size: 1.8rem; }
@media only screen and (max-width: 768px) {
.list ul li {
margin: 1.6rem 0 1.6rem 0; } }
.list ul li span {
display: inline-block;
width: 20.0rem;
text-align: right;
margin-right: 3.0rem; }
@media only screen and (max-width: 768px) {
.list ul li span {
display: block;
text-align: left; } }
.list ul li a {
font-size: 1.8rem;
color: #212121;
font-family: Lato, Helvetica, sans-serif;
font-weight: 700; }
.list ul li a:hover, .list ul li a:focus {
color: #1565c0; }
.centered {
display: flex;
align-items: center;
justify-content: center; }
.centered .about {
text-align: center; }
.centered .about h1 {
margin-top: 2.0rem;
margin-bottom: 0.5rem; }
.centered .about h2 {
margin-top: 1.0rem;
margin-bottom: 0.5rem;
font-size: 2.4rem; }
@media only screen and (max-width: 768px) {
.centered .about h2 {
font-size: 2.0rem; } }
.centered .about ul {
list-style: none;
margin: 3.0rem 0 1.0rem 0;
padding: 0; }
.centered .about ul li {
display: inline-block;
position: relative; }
.centered .about ul li a {
color: #212121;
text-transform: uppercase;
margin-left: 1.0rem;
margin-right: 1.0rem;
font-size: 1.6rem; }
.centered .about ul li a:hover, .centered .about ul li a:focus {
color: #1565c0; }
@media only screen and (max-width: 768px) {
.centered .about ul li a {
font-size: 1.4rem; } }
.centered .about ul li a i {
font-size: 3.2rem; }
.centered .error {
text-align: center; }
.centered .error h1 {
margin-top: 2.0rem;
margin-bottom: 0.5rem;
font-size: 4.6rem; }
@media only screen and (max-width: 768px) {
.centered .error h1 {
font-size: 3.2rem; } }
.centered .error h2 {
margin-top: 2.0rem;
margin-bottom: 3.2rem;
font-size: 3.2rem; }
@media only screen and (max-width: 768px) {
.centered .error h2 {
font-size: 2.8rem; } }
.navigation {
height: 6.0rem;
width: 100%; }
.navigation a, .navigation span {
display: inline;
font-size: 1.6rem;
font-family: Lato, Helvetica, sans-serif;
font-weight: 700;
line-height: 6.0rem;
color: #212121; }
.navigation a:hover, .navigation a:focus {
color: #1565c0; }
.navigation .navigation-title {
letter-spacing: 0.1rem;
text-transform: uppercase; }
.navigation .navigation-list {
float: right;
list-style: none;
margin-bottom: 0;
margin-top: 0; }
@media only screen and (max-width: 768px) {
.navigation .navigation-list {
position: absolute;
top: 6.0rem;
right: 0;
z-index: 5;
visibility: hidden;
opacity: 0;
padding: 0;
max-height: 0;
width: 100%;
background-color: #FAFAFA;
border-top: solid 2px #E0E0E0;
border-bottom: solid 2px #E0E0E0;
transition: opacity 0.25s, max-height 0.15s linear; } }
.navigation .navigation-list .navigation-item {
float: left;
margin: 0;
position: relative; }
@media only screen and (max-width: 768px) {
.navigation .navigation-list .navigation-item {
float: none !important;
text-align: center; }
.navigation .navigation-list .navigation-item a, .navigation .navigation-list .navigation-item span {
line-height: 5.0rem; } }
.navigation .navigation-list .navigation-item a, .navigation .navigation-list .navigation-item span {
margin-left: 1.0rem;
margin-right: 1.0rem; }
@media only screen and (max-width: 768px) {
.navigation .navigation-list .menu-separator {
border-top: 2px solid #212121;
margin: 0 8.0rem; }
.navigation .navigation-list .menu-separator span {
display: none; } }
.navigation #menu-toggle {
display: none; }
@media only screen and (max-width: 768px) {
.navigation #menu-toggle:checked + label {
color: #E0E0E0; }
.navigation #menu-toggle:checked + label + ul {
visibility: visible;
opacity: 1;
max-height: 100rem; } }
.navigation .menu-button {
display: none; }
@media only screen and (max-width: 768px) {
.navigation .menu-button {
display: block;
font-size: 2.4rem;
font-weight: 400;
line-height: 6.0rem;
color: #212121;
cursor: pointer; }
.navigation .menu-button:hover, .navigation .menu-button:focus {
color: #1565c0; } }
.pagination {
margin-top: 6.0rem;
text-align: center; }
.pagination li {
display: inline;
text-align: center; }
.pagination li span {
margin: 0;
text-align: center;
width: 3.2rem; }
.pagination li a span {
margin: 0;
text-align: center;
width: 3.2rem; }
.footer {
width: 100%;
text-align: center;
line-height: 2.0rem;
margin-bottom: 1.0rem; }
.footer a {
color: #1565c0; }
/*# sourceMappingURL=coder.css.map */

View File

@ -0,0 +1 @@
{"Target":"css/coder.css","MediaType":"text/css","Data":{}}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"Target":"css/styles.3fe40362df50d49db5018ca03fa5231ecd0fb34469614033aae05e1bf138441ff02925c097d2dc7c53e5792268d26daf9bc0477fcd58c396295764ec6769982c.css","MediaType":"text/css","Data":{"Integrity":"sha512-P+QDYt9Q1J21AYygP6UjHs0Ps0RpYUAzquBeG/E4RB/wKSXAl9LcfFPleSJo0m2vm8BHf81Yw5YpV2TsZ2mYLA=="}}

0
static/.gitkeep Normal file
View File

1
static/.htaccess Normal file
View File

@ -0,0 +1 @@
ErrorDocument 404 /404.html

5
static/_headers Normal file
View File

@ -0,0 +1,5 @@
/*
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Referrer-Policy: no-referrer
X-Content-Type-Options: nosniff

15
static/css/style.css Normal file
View File

@ -0,0 +1,15 @@
html {overflow-y: scroll}
:root { --bgcolor: black; --fontcolor: orange; --linkcolor: orange; --visitedcolor: orange; --precolor: #fff; --prebgcolor: #222;}
body{max-width:800px;margin:40px auto;padding:0 10px;font:14px/1.5 monospace;color:var(--fontcolor); background: var(--bgcolor)}a:link{color: var(--linkcolor)}a:visited{color: var(--visitedcolor)}a:active{color: var(--visitedcolor)}h1,h2,h3{line-height:1.2}
p > code{color: var(--precolor); background: var(--prebgcolor); padding:2px}
pre{color: var(--precolor); background: var(--prebgcolor); padding:24px; overflow-x: auto}
.ascii-art {
font-family: monospace;
white-space: pre;
line-height: 1;
}
article{padding:24px 0}
.center {display: block;margin-left: auto;margin-right: auto;width: 100%;}
img {display: block; max-width: 100%; height: auto;}
figcaption {color: #888; font: 12px/1.5 monospace; text-align: center;}
figure {margin: auto}

BIN
static/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 B

BIN
static/img/30m_dipole.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
static/img/antennapi01.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

BIN
static/img/antennapi02.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
static/img/antennapi03.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

BIN
static/img/antennapi04.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

BIN
static/img/antennapi05.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

BIN
static/img/antennapi06.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

BIN
static/img/diskette.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
static/img/esm2markdown.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

BIN
static/img/g90_mic_mod.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 KiB

BIN
static/img/g90_vfo_knob.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
static/img/mc_moshed.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
static/img/micha_moshed.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

BIN
static/img/obabp_1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
static/img/obabp_2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
static/img/qrz-sh.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
static/img/resistance.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
static/img/trackball1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

BIN
static/img/trackball2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
static/img/trackball3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
static/img/trackball4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

22
themes/smol/LICENSE.md Normal file
View File

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2016 Vimux
Copyright (c) 2020 colorchestra
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.

92
themes/smol/README.md Normal file
View File

@ -0,0 +1,92 @@
# smol
A minimal, monospaced blogging theme for Hugo that respects your privacy and is easy on your bandwidth. A demo can be found at https://smol-demo.morph.sh.
smol is based on [Blank](https://github.com/Vimux/Blank) created by [Vimux](https://github.com/Vimux).
![Screenshot](/images/tn.png)
## Features
- No JavaScript
- No Google spyware or tracking of any kind
- No other external dependencies, embedded fonts or comment sections
- Dark mode support (depending on your OS's setting)
## Installation
In your Hugo site `themes` directory, run:
```
git clone https://github.com/colorchestra/smol
```
Next, open `config.toml` in the base of the Hugo site and ensure the theme option is set to `smol`.
```
theme = "smol"
```
Lastly, add the following lines to your `config.toml` to set site parameters and make use of all the menu entries in the header and footer sections if you need them.
```
# Parameters
[params]
subtitle = "Your blog subtitle goes here!"
dateFmt = "02.01.2006 15:04"
# Header
[menu]
[[menu.main]]
identifier = "posts"
name = "Posts"
url = "/posts/"
weight = 1
[[menu.main]]
identifier = "categories"
name = "Categories"
url = "/categories/"
weight = 2
[[menu.main]]
identifier = "tags"
name = "Tags"
url = "/tags/"
weight = 3
# Footer
[[menu.footer]]
name = "Github"
url = "https://github.com/example"
weight = 1
[[menu.footer]]
name = "Mastodon"
url = "https://example.com/@user"
weight = 2
[[menu.footer]]
name = "Imprint"
url = "/imprint"
weight = 3
```
For more information read the official [quick start guide](https://gohugo.io/getting-started/quick-start/) of Hugo.
## Optional features
### Custom copyright text
Add `copyright = "Your text here"` - in the config.toml to change the copyright notice in the footer.
### Image captions
You can add captions to images (technically using `<figcaption>` HTML tags) by adding titles, like so: `![Alt text here](/path/to/image.png "Put your caption here!")`
## Contributing
Have you found a bug or got an idea for a new feature? Feel free to use the [issue tracker](https://github.com/colorchestra/smol/issues) to let me know. Or make directly a [pull request](https://github.com/colorchestra/smol/pulls).
## License
This theme is released under the [MIT license](https://github.com/colorchestra/smol/blob/master/LICENSE).

View File

@ -0,0 +1,4 @@
+++
title = "{{ replace .Name "-" " " | title }}"
date = {{ .Date }}
+++

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

BIN
themes/smol/images/tn.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

View File

@ -0,0 +1,11 @@
{{ if .Title }}
<figure>
<img src="{{ .Destination | safeURL }}" alt="{{ .Text }}" />
<figcaption>{{ .Title }}</figcaption>
</figure>
{{ else }}
<figure>
<img src="{{ .Destination | safeURL }}" alt="{{ .Text }}" />
</figure>
{{ end }}

View File

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="{{ .Site.LanguageCode | default "en-us" }}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<style type=text/css>body{font-family:monospace;}</style>
<title>{{ .Title }}</title>
{{ with .Site.Params.description }}<meta name="description" content="{{ . }}">{{ end }}
{{ with .Site.Params.author }}<meta name="author" content="{{ . }}">{{ end }}
<link rel="stylesheet" href="{{ "css/style.css" | relURL }}">
{{ range .Site.Params.customCSS -}}
<link rel="stylesheet" href="{{ . | relURL }}?rnd={{ now.Unix }}">
{{- end }}
{{ with .OutputFormats.Get "RSS" -}}
{{ printf `<link rel="%s" type="%s" href="%s" title="%s">` .Rel .MediaType.Type .RelPermalink $.Site.Title | safeHTML }}
{{- end }}
</head>
<body>
{{ partial "header" . }}
{{ block "main" . }}{{ end }}
{{ partial "footer" . }}
</body>
</html>

View File

@ -0,0 +1,26 @@
{{ define "main" }}
<main>
{{ $listtitle := .Title }}
{{ if or .Title .Content }}
<div>
{{ with .Title }}<h1>{{ . }}</h1>{{ end }}
{{ with .Content }}<div>{{ . }}</div>{{ end }}
</div>
{{ end }}
<ul>
{{ range .Paginator.Pages }}
<li>
<div class="post-title">
{{ if eq $listtitle "Posts" }}
{{ .Date.Format "2006-01-02" }} <a href="{{ .RelPermalink }}">{{.Title }}</a>
{{ else }}
<a href="{{ .RelPermalink }}">{{.Title }}</a>
{{ end }}
</div>
</li>
{{ end }}
</ul>
{{ partial "pagination.html" . }}
</main>
{{ end }}

View File

@ -0,0 +1,16 @@
{{ define "main" }}
<main>
<article>
<h1>{{ .Title }}</h1>
<b><time>{{ .Date.Format (default "2006-01-02 15:04:05" .Site.Params.dateFmt) }}</time></b>
{{ range .Params.tags }}
<a href="{{ "/tags/" | relLangURL }}{{ . | urlize }}">{{ . }}</a>
{{ end }}
<div>
{{ .Content }}
</div>
</article>
</main>
{{ partial "sidebar.html" . }}
{{ end }}

View File

@ -0,0 +1,13 @@
<article>
<h1><a href="{{ .Permalink }}">{{ .Title }}</a></h1>
<b><time>{{ .Date.Format (default "2006-01-02 15:04:05" .Site.Params.dateFmt) }}</time></b>
{{ range .Params.tags }}
<a href="{{ "/tags/" | relLangURL }}{{ . | urlize }}">{{ . }}</a>
{{ end }}
<div>
{{ .Summary }}
{{ if .Truncated }}
<a href="{{ .Permalink }}">Read more...</a>
{{ end }}
</div>
</article>

View File

@ -0,0 +1,9 @@
{{ define "main" }}
<main>
{{ $paginator := .Paginate (where .Site.RegularPages "Type" "in" .Site.Params.mainSections) }}
{{ range $paginator.Pages }}
{{ .Render "summary" }}
{{ end }}
{{ partial "pagination.html" . }}
</main>
{{ end }}

View File

@ -0,0 +1,7 @@
<footer>
<p>&copy; {{ now.Year }} <a href="{{ .Site.BaseURL }}"><b>{{ if .Site.Copyright }}{{ .Site.Copyright }}{{ else }}{{ .Site.Title }}{{ end }}</b></a>.
{{- range .Site.Menus.footer }}
<a href="{{ .URL }}"><b>{{ .Name }}</b></a>.
{{- end }}
</p>
</footer>

View File

@ -0,0 +1,16 @@
<header>
{{ strings.Repeat ( .Site.Title | len | add 6 ) "=" }}<br>
== <a href="{{ .Site.BaseURL }}">{{ .Site.Title }}</a> ==<br>
{{ strings.Repeat ( .Site.Title | len | add 6 ) "=" }}
<div style="float: right;">{{ .Site.Params.subtitle }}</div><br>
<p>
<nav>
<a href="/"><b>Start</b></a>.
{{ with .Site.Menus.main }}
{{ range . }}
<a href="{{ .URL | relURL }}"><b>{{ .Name }}</b></a>.
{{ end }}
</nav>
</p>
{{ end }}
</header>

View File

@ -0,0 +1,9 @@
<div>
{{ if .Paginator.HasPrev }}
<a href="{{ .Paginator.Prev.URL }}">Previous Page</a>
{{ end }}
{{ .Paginator.PageNumber }} of {{ .Paginator.TotalPages }}
{{ if .Paginator.HasNext }}
<a href="{{ .Paginator.Next.URL }}">Next Page</a>
{{ end }}
</div>

View File

@ -0,0 +1,14 @@
<aside>
<div>
<div>
<h3>LATEST POSTS</h3>
</div>
<div>
<ul>
{{ range first 5 (where .Site.RegularPages "Type" "in" .Site.Params.mainSections) }}
<li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
{{ end }}
</ul>
</div>
</div>
</aside>

Some files were not shown because too many files have changed in this diff Show More