Compare commits
11 Commits
e01d88b0c6
...
898f0d7e93
Author | SHA1 | Date | |
---|---|---|---|
898f0d7e93 | |||
e94ebaa037 | |||
b956166d24 | |||
c442270362 | |||
f33a7a38a2 | |||
94771a2aa7 | |||
fbf00cd154 | |||
6a66df4a92 | |||
48696ad06c | |||
aa8fe46b43 | |||
e0bb762551 |
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
public/
|
||||
_gen/
|
||||
|
||||
|
19
README.md
@ -6,24 +6,23 @@ Site generated with [Hugo][] using the [hermit-v2][] theme.
|
||||
|
||||
Build site:
|
||||
|
||||
```
|
||||
$ docker compose up build
|
||||
```bash
|
||||
docker compose up build
|
||||
```
|
||||
|
||||
Run development server with live refresh:
|
||||
Run development server with live refresh and draft as well as future post
|
||||
rendering enabled:
|
||||
|
||||
```
|
||||
$ docker compose up server
|
||||
```bash
|
||||
docker compose up server
|
||||
```
|
||||
|
||||
Add new posts:
|
||||
|
||||
```bash
|
||||
docker compose up -d server
|
||||
docker compose exec server new content/posts/2024-07-31-my-new-blog-post.md
|
||||
```
|
||||
$ docker compose up -d server
|
||||
$ docker compose exec server new content/posts/2024-07-31-my-new-blog-post.md
|
||||
```
|
||||
|
||||
|
||||
|
||||
[hermit-v2]: https://github.com/1bl4z3r/hermit-V2
|
||||
[Hugo]: https:/gohugo.io
|
75
assets/images/favicon.svg
Normal file
@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="83mm"
|
||||
height="83mm"
|
||||
viewBox="0 0 82.999996 82.999991"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="1.0 (1.0+r73+1)"
|
||||
sodipodi:docname="Gänseliesel-Logo rund.svg"
|
||||
inkscape:export-filename="/home/daniel/cloud/Photos/Hintergrundbilder/Gänseliesel-Logo rund.png"
|
||||
inkscape:export-xdpi="162.82001"
|
||||
inkscape:export-ydpi="162.82001">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.4684"
|
||||
inkscape:cx="108.33847"
|
||||
inkscape:cy="178.35599"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-rotation="0"
|
||||
showgrid="false"
|
||||
fit-margin-top="3"
|
||||
fit-margin-left="3"
|
||||
fit-margin-right="3"
|
||||
fit-margin-bottom="3"
|
||||
lock-margins="true" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title>(c) Daniel Kraus <www.bovender.de></dc:title>
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-56.138771,-86.109581)">
|
||||
<circle
|
||||
r="39"
|
||||
cy="128.10957"
|
||||
cx="97.609604"
|
||||
id="path857"
|
||||
style="color:black;overflow:visible;fill:#696969;fill-opacity:1;stroke:none;stroke-width:2.00001;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cscsssccscccsscsssccccscccssscsscsssscsccccccccccssccccssscsscssssscscccccsccsccccccccc"
|
||||
style="fill:navy;stroke:white;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linejoin:bevel"
|
||||
d="m 73.66954,156.68256 c -0.0257,-0.0212 -0.04676,-1.16622 -0.04676,-2.54442 v -2.50582 l -0.622191,-0.38414 c -1.041429,-0.64296 -1.426937,-2.10829 -1.070799,-4.07019 0.185083,-1.01962 0.168352,-1.20734 -0.157396,-1.76658 -0.703944,-1.2085 -0.948192,-4.22473 -0.610203,-7.5353 0.109691,-1.07467 0.224045,-1.39705 0.642726,-1.81227 0.438724,-0.43508 0.509281,-0.65636 0.509281,-1.5972 0,-0.89228 0.136876,-1.37491 0.747939,-2.63718 1.591474,-3.28755 3.650313,-5.74902 5.158472,-6.16732 0.401471,-0.11129 1.546325,-0.20294 2.544116,-0.20351 2.028793,-0.001 3.643675,-0.45634 5.034194,-1.41896 1.09234,-0.75621 3.697965,-3.58834 4.44801,-4.83468 l 0.640805,-1.06481 -0.350243,-0.64968 c -0.192622,-0.35731 -0.668559,-0.90152 -1.057631,-1.20935 -1.214761,-0.96111 -1.402229,-2.68752 -0.442115,-4.07152 0.261205,-0.37652 0.474599,-0.84815 0.474215,-1.04805 -7.42e-4,-0.40984 -0.565068,-1.40157 -1.144496,-2.01146 -0.333922,-0.3515 -0.374963,-0.58219 -0.304777,-1.7134 0.0934,-1.5051 0.471711,-2.36391 1.241469,-2.81815 0.307214,-0.18128 0.711892,-0.69671 0.936083,-1.19225 0.504605,-1.11535 3.143032,-3.706003 4.442274,-4.361847 0.595113,-0.300396 1.406641,-0.523321 2.121739,-0.58282 1.085968,-0.09039 1.224711,-0.158 2.229284,-1.087097 1.278124,-1.182077 2.812644,-2.223967 4.230694,-2.872493 2.74258,-1.25428 8.56759,-0.434746 11.85918,1.668514 1.45844,0.931903 4.02461,3.493836 4.20038,4.193423 0.0692,0.27543 0.33015,0.70489 0.57988,0.95437 0.24974,0.24945 0.45406,0.61947 0.45406,0.82223 0,0.20277 0.28544,0.96864 0.63432,1.70193 0.89526,1.88167 1.1891,2.79911 1.4438,4.50792 0.32272,2.16504 0.2756,3.01135 -0.25124,4.51229 -0.47937,1.3657 -1.00207,2.09536 -3.25909,4.54957 -1.73736,1.88914 -1.93271,2.37824 -1.93271,4.83888 0,1.96414 -0.0203,2.0706 -0.44756,2.35027 -0.26617,0.17422 -0.62899,0.24744 -0.89525,0.18069 -0.63539,-0.15931 -1.43808,0.19667 -1.64004,0.72732 -0.22403,0.58862 -0.51601,0.75501 -1.23952,0.70633 -0.85373,-0.0574 -1.59229,0.26091 -1.45207,0.6259 0.1529,0.39806 -0.57173,1.1417 -1.24329,1.27587 -0.37802,0.0756 -0.62843,0.30247 -0.85117,0.77139 -0.48801,1.0273 -1.18448,1.42249 -2.51826,1.42886 -1.32822,0.007 -1.42602,-0.0484 -3.50099,-1.96244 -0.84898,-0.7831 -1.6061,-1.42254 -1.68248,-1.42098 -0.32474,0.007 -0.57603,0.3556 -1.20847,1.67785 -1.555805,3.25282 -1.657654,3.5644 -1.769822,5.41463 l -0.107571,1.77504 1.099652,0.74367 c 1.280911,0.86625 2.842061,2.13904 3.834611,3.12634 0.54014,0.53728 0.72766,0.89812 0.8249,1.58734 0.0693,0.49058 0.33931,1.26394 0.60021,1.71855 l 0.47434,0.82657 0.36743,-0.77988 c 0.20208,-0.42894 0.44653,-0.77989 0.54317,-0.77989 0.0967,0 0.29875,-0.29412 0.4491,-0.6536 0.15034,-0.35949 0.36134,-0.65361 0.46883,-0.65361 0.10757,0 0.14348,-0.084 0.0799,-0.18675 -0.0636,-0.10269 0.0156,-0.18674 0.1759,-0.18674 0.1603,0 0.29144,-0.083 0.29144,-0.18455 0,-0.1015 0.33649,-0.23828 0.74776,-0.30398 0.41126,-0.0656 0.74776,-0.18317 0.74776,-0.26105 0,-0.0778 0.2734,-0.26955 0.60755,-0.42593 1.04677,-0.48989 4.87233,-0.18305 5.95124,0.47733 0.61483,0.37632 1.42997,1.87491 1.76605,3.24673 0.35754,1.45941 0.66483,2.03534 1.40645,2.63593 0.28695,0.23237 0.58092,0.69177 0.65328,1.02089 0.0723,0.32911 0.36623,0.89531 0.65304,1.25821 0.71105,0.89969 0.92402,1.82361 0.9269,4.02122 0.001,1.02709 0.0901,2.40659 0.19706,3.06554 0.16565,1.01985 0.15054,1.24214 -0.10161,1.49396 -17.98696,11.95593 -33.854294,9.38426 -47.53174,0.0543 z M 90.631571,114.6264 c 0.104392,0 0.189694,-0.093 0.189694,-0.20673 0,-0.11368 -0.13049,-0.15667 -0.290125,-0.0956 -0.159555,0.0611 -0.242313,0.0339 -0.183891,-0.0605 0.175174,-0.28313 -0.269127,-0.43381 -0.562339,-0.19072 -0.284613,0.23596 -0.355038,0.86752 -0.154852,1.38867 0.09485,0.24697 0.183931,0.19621 0.464597,-0.26485 0.190979,-0.31371 0.432591,-0.57038 0.536916,-0.57038 z m -0.917191,0.0778 c 0.0093,-0.21755 0.05326,-0.2618 0.113003,-0.11288 0.05405,0.13481 0.04743,0.29587 -0.01471,0.35794 -0.06213,0.0621 -0.106247,-0.0483 -0.09817,-0.24511 z"
|
||||
id="path935" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.2 KiB |
68
assets/js/mastodon-share.js
Normal file
@ -0,0 +1,68 @@
|
||||
|
||||
// I got the key, I got the secret…
|
||||
let key = 'mastodon-instance';
|
||||
let instance = localStorage.getItem(key);
|
||||
|
||||
// get the link from the DOM
|
||||
const button = document.querySelector('.mastodon-share');
|
||||
|
||||
// refresh the link with the instance name
|
||||
const refreshlink = (instance) => {
|
||||
button.href = `https://${instance}/share?text=${encodeURIComponent(document.title)}%0A${encodeURIComponent(location.href)}`;
|
||||
}
|
||||
|
||||
// got it? Let's go!
|
||||
if (button) {
|
||||
// labels and texts from the link
|
||||
let prompt = button.dataset.prompt || 'Please tell me your Mastodon instance';
|
||||
let editlabel = button.dataset.editlabel || 'Edit your Mastodon instance';
|
||||
let edittext = button.dataset.edittext || '✏️';
|
||||
|
||||
// Ask the user for the instance name and set it…
|
||||
const setinstance = _ => {
|
||||
instance = window.prompt(prompt, instance);
|
||||
if(instance) {
|
||||
localStorage.setItem(key, instance);
|
||||
createeditbutton();
|
||||
refreshlink(instance);
|
||||
button.click();
|
||||
}
|
||||
}
|
||||
|
||||
// create and insert the edit link
|
||||
const createeditbutton = _ => {
|
||||
if (document.querySelector('button.mastodon-edit')) return;
|
||||
let editlink = document.createElement('button');
|
||||
editlink.innerText = edittext;
|
||||
editlink.classList.add('mastodon-edit');
|
||||
editlink.title = editlabel;
|
||||
editlink.ariaLabel = editlabel;
|
||||
editlink.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
localStorage.removeItem(key);
|
||||
setinstance();
|
||||
});
|
||||
button.insertAdjacentElement('afterend', editlink);
|
||||
}
|
||||
|
||||
// if there is a value in localstorage, create the edit link
|
||||
if(localStorage.getItem(key)) {
|
||||
createeditbutton();
|
||||
}
|
||||
|
||||
// When a user clicks the link
|
||||
button.addEventListener('click', (e) => {
|
||||
|
||||
// If the user has already entered their instance
|
||||
// and it is in localstorage write out the link href
|
||||
// with the instance and the current page title and URL
|
||||
if(localStorage.getItem(key)) {
|
||||
refreshlink(localStorage.getItem(key));
|
||||
// otherwise, prompt the user for their instance and save it to localstorage
|
||||
} else {
|
||||
e.preventDefault();
|
||||
setinstance();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
54
assets/scss/_predefined.scss
Normal file
@ -0,0 +1,54 @@
|
||||
// Colors
|
||||
$theme: hsl(172, 99%, 26%);
|
||||
$text: hsl(204, 28%, 93%);
|
||||
$light-grey: #292e32; // #494f5c;
|
||||
$dark-grey: #3B3E48;
|
||||
$highlight-grey: #7d828a;
|
||||
$midnightblue: #2c3e50;
|
||||
$typewriter: hsl(172, 100%, 36%);
|
||||
|
||||
// Fonts
|
||||
$fonts: "IBM Plex Sans Light", "Trebuchet MS", Verdana, "Verdana Ref", "Segoe UI", Candara, "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Tahoma, sans-serif;
|
||||
$code-fonts: Consolas, "Andale Mono WT", "Andale Mono", Menlo, Monaco, "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", "Courier New", Courier, "YaHei Consolas Hybrid", monospace, "Segoe UI Emoji", "PingFang SC", "Microsoft YaHei";
|
||||
|
||||
//Admonition
|
||||
$admonition-background: (
|
||||
'note': rgba(68, 138, 255, 0.1),
|
||||
'info': rgba(0, 184, 212, 0.1),
|
||||
'tip': rgba(0, 191, 165, 0.1),
|
||||
'success': rgba(0, 200, 83, 0.1),
|
||||
'warning': rgba(255, 145, 0, 0.1),
|
||||
'failure': rgba(255, 82, 82, 0.1),
|
||||
'danger': rgba(255, 23, 68, 0.1),
|
||||
'bug': rgba(245, 0, 87, 0.1),
|
||||
) !default;
|
||||
|
||||
$admonition-color: (
|
||||
'note': #448aff,
|
||||
'info': #00b8d4,
|
||||
'tip': #00bfa5,
|
||||
'success': #00c853,
|
||||
'warning': #ff9100,
|
||||
'failure': #ff5252,
|
||||
'danger': #ff1744,
|
||||
'bug': #f50057,
|
||||
) !default;
|
||||
|
||||
// Mixins
|
||||
@mixin dimmed {
|
||||
opacity: .6;
|
||||
}
|
||||
|
||||
@mixin aTag {
|
||||
a {
|
||||
word-wrap: break-word;
|
||||
border: none;
|
||||
box-shadow: inset 0 -4px 0 $theme;
|
||||
transition-property: box-shadow;
|
||||
transition-duration: .1s;
|
||||
|
||||
&:hover {
|
||||
box-shadow: inset 0 -1em 0 $theme;
|
||||
}
|
||||
}
|
||||
}
|
35
config.toml
@ -1,5 +1,6 @@
|
||||
baseURL = 'https://bovender.de/'
|
||||
baseURL = 'https://www.bovender.de/'
|
||||
languageCode = 'en-us'
|
||||
defaultContentLanguage = 'en'
|
||||
title = 'bovender'
|
||||
theme = "hermit-v2"
|
||||
|
||||
@ -26,13 +27,12 @@ lastmod = ["lastmod", ":git", "date", "publishDate"]
|
||||
publishDate = ["publishDate", "date"]
|
||||
expiryDate = ["expiryDate"]
|
||||
|
||||
|
||||
[params.author]
|
||||
name = "Daniel Kraus"
|
||||
about = "CHANGE SITE AUTHOR ABOUT"
|
||||
about = "/about"
|
||||
|
||||
[blackfriday]
|
||||
# hrefTargetBlank = true
|
||||
hrefTargetBlank = true
|
||||
# noreferrerLinks = true
|
||||
# nofollowLinks = true
|
||||
|
||||
@ -58,14 +58,16 @@ expiryDate = ["expiryDate"]
|
||||
dateformNum = "2006-01-02"
|
||||
dateformNumTime = "2006-01-02 15:04 -0700"
|
||||
|
||||
# description = "CHANGE ME SITE DESC RIPTION"
|
||||
description = "Daniel Kraus' personal homepage"
|
||||
# images = [""]
|
||||
themeColor = "#494f5c"
|
||||
themeColor = "#292e32"
|
||||
|
||||
homeSubtitle = "Daniel Kraus"
|
||||
footerCopyright = "all rights reserved"
|
||||
# bgImg = ""
|
||||
gitUrl = "https://github.com/1bl4z3r/hermit-V2/tree/staging"
|
||||
|
||||
ShowLastmod = true
|
||||
gitUrl = "https://git.bovender.de/daniel/blog"
|
||||
|
||||
justifyContent = true
|
||||
|
||||
@ -75,8 +77,8 @@ expiryDate = ["expiryDate"]
|
||||
homeSubtitlePrinter = true
|
||||
scrollToTop = true
|
||||
global_mathjax = false
|
||||
# readTime = true
|
||||
# readTimeSeparator = "CHANGE ME READ TIME"
|
||||
readTime = false
|
||||
readTimeSeparator = "~"
|
||||
# legacyLayout = false
|
||||
shareSocial = true
|
||||
# googleTagManager = "GTM-XXXXXXXX"
|
||||
@ -85,8 +87,8 @@ expiryDate = ["expiryDate"]
|
||||
# pinned = "Pinned Posts"
|
||||
# pinnedSVGname = "pin"
|
||||
# descriptionInPosts= true
|
||||
# initialPublish = "Initally Posted on: "
|
||||
# human = ["single","posts"]
|
||||
initialPublish = "Initally Posted on: "
|
||||
human = ["single","posts"]
|
||||
|
||||
[[params.socialLinks]]
|
||||
name = "mastodon"
|
||||
@ -111,11 +113,16 @@ expiryDate = ["expiryDate"]
|
||||
[menu]
|
||||
|
||||
[[menu.main]]
|
||||
name = "Posts"
|
||||
name = "Blog"
|
||||
url = "posts/"
|
||||
weight = 10
|
||||
|
||||
[[menu.main]]
|
||||
name = "About"
|
||||
name = "About bovender"
|
||||
url = "about/"
|
||||
weight = 20
|
||||
weight = 20
|
||||
|
||||
[[menu.main]]
|
||||
name = "Impressum"
|
||||
url = "impressum/"
|
||||
weight = 30
|
BIN
content/about/ggap-ev.png
Normal file
After Width: | Height: | Size: 2.9 MiB |
@ -1,8 +1,47 @@
|
||||
---
|
||||
title: "Content Placeholder"
|
||||
_build:
|
||||
render: never
|
||||
list: never
|
||||
publishResources: false
|
||||
title: "About bovender"
|
||||
toc: true
|
||||
---
|
||||
|
||||
I'm a physician-scientist from Germany.
|
||||
|
||||
[Bovenden](https://www.bovenden.de) is the name of the village/small town
|
||||
in lovely Lower Saxony, Germany, where I grew up. Hence I'm a bovender --
|
||||
not _the_ bovender, of course, just one of many, but proud to be one :-)
|
||||
|
||||
Computers have been part of my life ever since I programmed my dad's
|
||||
calculator back in the 1980's.
|
||||
|
||||
## Portfolio -- websites
|
||||
|
||||
### [ggap-ev.org](https://ggap-ev.org)
|
||||
|
||||
{{< figure src="ggap-ev.png">}}
|
||||
|
||||
### [nephrowiki.de](https://nephrowiki.de)
|
||||
|
||||
{{< figure src="nephrowiki.png">}}
|
||||
|
||||
## Portfolio -- software
|
||||
|
||||
### [Daniel's XL Toolbox](https://xltoolbox.net)
|
||||
|
||||
{{< figure src="xltoolbox.png">}}
|
||||
|
||||
### [LinkTitles](https://github.com/bovender/linktitles)
|
||||
|
||||
LinkTitles is a [MediaWiki](https://mediawiki.org) extension that automatically
|
||||
links terms to existing pages in a Wiki.
|
||||
|
||||
### [PubmedParser](https://github.com/bovender/pubmedparser)
|
||||
|
||||
PubmedParser is a [MediaWiki](https://mediawiki.org) extension to include and
|
||||
reference articles from [Pubmed](https://pubmed.gov) by PMID.
|
||||
|
||||
## Server administration
|
||||
|
||||
I have 10+ years experience with running and administrating my own server.
|
||||
This includes running a mail and an IMAP server, hosting my own
|
||||
[Nextcloud](https://nextcloud.com) and [Gitea](https://gitea.io) instances,
|
||||
[Mastodon for Nephrology](https://neph.social)
|
||||
and more. Almost all of my services are dockerized.
|
||||
|
BIN
content/about/nephrowiki.png
Normal file
After Width: | Height: | Size: 2.2 MiB |
BIN
content/about/xltoolbox.png
Normal file
After Width: | Height: | Size: 2.4 MiB |
46
content/impressum.md
Normal file
@ -0,0 +1,46 @@
|
||||
---
|
||||
title: "Impressum und Datenschutz"
|
||||
date: 2024-07-31T12:42:53Z
|
||||
draft: false
|
||||
---
|
||||
|
||||
Dr. Daniel Kraus
|
||||
H‌ö‌hen‌str‌aße 1‌5
|
||||
65451 K‌e‌l‌s‌t‌e‌r‌b‌a‌c‌h
|
||||
Tel. (0 61 07‌) 7 5‌6 88 4‌0
|
||||
<bovender@bovender.de>
|
||||
|
||||
Ich bitte, von Anrufen abzusehen. Über Mail oder die verlinkten
|
||||
sozialen Netzwerke (siehe Icons) bin ich i.d.R. kurzfristig
|
||||
erreichbar.
|
||||
|
||||
## Mailserver bovender.de
|
||||
|
||||
Der Mailserver bovender.de ist zuständig für die Domains:
|
||||
|
||||
- [bantel-stiftung.de](https://bantel-stiftung.de)
|
||||
- [bantelstiftung.de](https://bantelstiftung.de)
|
||||
- [bovender.de](https://bovender.de)
|
||||
- [gemeinsam-gegen-armut.org](https://gemeinsam-gegen-armut.org)
|
||||
- [ggap-ev.org](https://ggap-ev.org)
|
||||
- [mainzer-niere.de](https://mainzer-niere.de)
|
||||
- [neph.social](https://neph.social)
|
||||
- [nephrowiki.de](https://nephrowiki.de)
|
||||
- [nierenverein.de](https://nierenverein.de)
|
||||
- [xltoolbox.net](https://xltoolbox.net)
|
||||
|
||||
## Datenschutz
|
||||
|
||||
Diese Website erfasst keine personenbezogenen Daten, und es werden keine
|
||||
Dienste von Drittfirmen in Anspruch genommen.
|
||||
|
||||
Es findet eine anonymisierte Erfassung von Seitenbesuchen statt, die keine
|
||||
Rückverfolgung zu einzelnen Personen/Geräten ermöglicht.
|
||||
|
||||
## Dank
|
||||
|
||||
Besonderer Dank an [Christian Heilmann][] für das Script [mastodon-share][],
|
||||
um Links leicht auf Mastodon zu posten.
|
||||
|
||||
[Christian Heilmann]: https://christianheilmann.com/2023/08/18/adding-a-share-to-mastodon-link-to-any-web-site-and-here/
|
||||
[mastodon-share]: https://github.com/codepo8/mastodon-share
|
204
content/posts/2024-08-05-linux-on-thinkpad-P14s-Gen-5/index.md
Normal file
@ -0,0 +1,204 @@
|
||||
---
|
||||
title: "Experience with running Fedora Linux on a Thinkpad P14s Gen 5"
|
||||
description: "Everything works out of the box, but the keyboard and the battery leave something to be desired."
|
||||
date: 2024-08-05T21:00:00Z
|
||||
draft: false
|
||||
toc: true
|
||||
scrolltotop: true
|
||||
tags:
|
||||
- Thinkpad
|
||||
- Linux
|
||||
- Fedora
|
||||
- NVIDIA
|
||||
---
|
||||
|
||||
I have recently acquired a Lenovo Thinkpad P14s Gen 5. As of the time of writing
|
||||
-- summer of '24 -- these machines are brand new, and so is their architecture:
|
||||
Intel Core Ultra (Meteor Lake) with a dedicated NVIDIA GPU. Here I report my
|
||||
experience with running Linux with the [KDE Plasma][] desktop on this machine.
|
||||
|
||||
My previous daily driver was a T480s (see my old blog post over at [xltoolbox.net][]
|
||||
for a report). I also administer two different X1 Carbons (5th generation and
|
||||
9th generation), however, I don't use these very often myself.
|
||||
|
||||
Here are the specs (the 1 TB SSD has been swapped for a Samsung 990 PRO with 2 TB).
|
||||
|
||||
```plain
|
||||
daniel@seppel9 ~> fastfetch
|
||||
.',;::::;,'. daniel@seppel9
|
||||
.';:cccccccccccc:;,. --------------
|
||||
.;cccccccccccccccccccccc;. OS: Fedora Linux 40 (KDE Plasma) x86_64
|
||||
.:cccccccccccccccccccccccccc:. Host: 21G3S00A00 (ThinkPad P14s Gen 5)
|
||||
.;ccccccccccccc;.:dddl:.;ccccccc;. Kernel: Linux 6.9.11-200.fc40.x86_64
|
||||
.:ccccccccccccc;OWMKOOXMWd;ccccccc:. Uptime: 1 hour, 47 mins
|
||||
.:ccccccccccccc;KMMc;cc;xMMc;ccccccc:. Packages: 4338 (rpm)
|
||||
,cccccccccccccc;MMM.;cc;;WW:;cccccccc, Shell: fish 3.7.0
|
||||
:cccccccccccccc;MMM.;cccccccccccccccc: Display (LEN8AB1): 3072x1920 @ 120 Hz (as 2048x1280) in 14″ [Built-in]
|
||||
:ccccccc;oxOOOo;MMM000k.;cccccccccccc: DE: KDE Plasma 6.1.3
|
||||
cccccc;0MMKxdd:;MMMkddc.;cccccccccccc; WM: KWin (Wayland)
|
||||
ccccc;XMO';cccc;MMM.;cccccccccccccccc' WM Theme: Breeze
|
||||
ccccc;MMo;ccccc;MMW.;ccccccccccccccc; Theme: Breeze (Dark) [Qt], Breeze [GTK3]
|
||||
ccccc;0MNc.ccc.xMMd;ccccccccccccccc; Icons: breeze-dark [Qt], breeze-dark [GTK3/4]
|
||||
cccccc;dNMWXXXWM0:;cccccccccccccc:, Font: IBM Plex Sans (10pt) [Qt], IBM Plex Sans (10pt) [GTK3/4]
|
||||
cccccccc;.:odl:.;cccccccccccccc:,. Cursor: breeze (24px)
|
||||
ccccccccccccccccccccccccccccc:'. Terminal: konsole 24.5.2
|
||||
:ccccccccccccccccccccccc:;,.. CPU: Intel(R) Core(TM) Ultra 7 155H (22) @ 4,80 GHz
|
||||
':cccccccccccccccc::;,. GPU 1: Intel rc Graphics @ 2,25 GHz [Integrated]
|
||||
GPU 2: NVIDIA RTX 500 Ada Generation Laptop GPU
|
||||
Memory: 9,13 GiB / 62,29 GiB (15%)
|
||||
Swap: 302,50 MiB / 104,00 GiB (0%)
|
||||
Disk (/): 18,77 GiB / 146,59 GiB (13%) - ext4
|
||||
Disk (/home): 524,56 GiB / 1,55 TiB (33%) - ext4
|
||||
Local IP (wlp0s20f3): 192.168.3.114/24
|
||||
Battery: 93% [AC Connected]
|
||||
Locale: en_US.UTF-8
|
||||
```
|
||||
|
||||
## Difficulties and finally success with installing Linux
|
||||
|
||||
At first, I was totally unable to install [KDE neon][], my preferred Linux distribution,
|
||||
on this system. I freaked out. (I don't care if it's officially a 'distribution' or not.)
|
||||
The live CD just would not boot. It did work in safe graphics mode, but when I installed
|
||||
the system onto the laptop, I was once again unable to boot into Plasma.
|
||||
(I already posted in the [KDE forum][] about this).
|
||||
|
||||
At some point it occurred to me that I may need to try a distribution, so I tried [Fedora][]
|
||||
-- and it worked!! In order to boot the live CD, I also had to choose basic graphics mode
|
||||
just like with KDE neon (which is Ubuntu under the hood). Once I had the live desktop up
|
||||
and running, I could enable the NVIDIA repositories, so that the NVIDIA drivers were
|
||||
included during system installation. Luckily, the Fedora Project provides a [KDE spin][]
|
||||
so that I could continue to use my favorite desktop environment.
|
||||
|
||||
## Hardware
|
||||
|
||||
Except for the initial difficulties getting this system with a dedicated NVIDIA GPU
|
||||
to run Linux, everything else just works out of the box. Nice! :-)
|
||||
|
||||
The **trackpoint** works as usual. This is really the main reason why I keep buying
|
||||
Thinkpads. A laptop without trackpoint is a no-go for me. In fact, I did consider buying
|
||||
a MacBook Pro, but the absence of a trackpoint and the uncertainty whether I could do
|
||||
my beloved Linux foo with MacOS made me stick with a Thinkpad.
|
||||
|
||||
The **fingerprint scanner** is integrated into the power button. While not essential, it's
|
||||
a nice gimmick and KDE Plasma provides a pretty UI to set it up. Currently, logging
|
||||
into the system after booting is not (yet) supported, but unlocking (e.g., after resume
|
||||
from sleep) works very well.
|
||||
|
||||
The 3k **screen** is really good, it's very bright and super crisp. At 100%, the
|
||||
user interface is quite tiny. Luckily, with Wayland, fractional scaling is now
|
||||
easy to accomplish and reliable. With a scale factor of 1.2 (120%), I am very happy
|
||||
with my P14s' display. Interestingly though, the corners are rounded, even though
|
||||
the laptop frame has sharp corners. I tend to think: If you have enough time wondering
|
||||
about something like this, it's probably time to take a break and do something else
|
||||
for a while.
|
||||
|
||||
Unfortunately, the **keyboard** is the worst that I have ever had in any Thinkpad.
|
||||
It feels like typing on jelly. Luckily, for most of the heavy-duty work, I connect
|
||||
the laptop to a Thunderbolt dock with a proper mechanical keyboard attached.
|
||||
I wonder why Lenovo does not equip this machine with the same keyboard as in the
|
||||
other models -- given the price tag of this machine, the extra bucks surely cannot
|
||||
make such a big difference?
|
||||
|
||||
**Camera**, mike, and speakers just work. No problem running Zoom. I have not yet
|
||||
tried out Teams.
|
||||
|
||||
## Form factor and weight
|
||||
|
||||
The P14s is somewhat bigger than the old T480s and certainly somewhat heavier.
|
||||
Before deciding on the purchase, I carefully thought about my use cases and decided
|
||||
that I can live with an extra 200-300 grams that I mostly only carry onto and
|
||||
off from the commute train, as well as on my bicycle's rack. Therefore, I made a
|
||||
decision for the extra performance (with dedicated GPU, which the alternative
|
||||
models, i.e. X1 Carbons or T14s's do not offer).)
|
||||
|
||||
Lenovo [says][p14s-weight] the P14s starts at 1.6 kg, which compares to a MacBook Pro's
|
||||
nominal weight. On our kitchen scale, my P14s weighs 1.74 kg.
|
||||
|
||||
In real life, the laptop's body is somewhat bigger than the actual casing, because
|
||||
it has a very long "foot" underneath it. This ensures proper ventilation, because
|
||||
the two fans blow out the warm air underneath the laptop. While this "foot" makes
|
||||
the P14s rather thick, it turns out that this also provides a good grip when pulling
|
||||
it ouf of a bag or carrying it around.
|
||||
|
||||
I have yet to come to terms with the new camera casing that all new Thinkpads
|
||||
seem to have nowadays.
|
||||
|
||||
{{< figure src="p14s -camera-casing.jpg"
|
||||
alt="A photograph of the camera casing of a Thinkpad P14s Gen 5"
|
||||
caption="The camera casing. It disrupts the smooth surface of the Thinkpad.">}}
|
||||
|
||||
{{< figure src="p14s-foot.jpg"
|
||||
alt="A photograph of the 'foot' underneath a Thinkpad P14s Gen 5"
|
||||
caption="The 'foot' underneath the P14s makes it thicker, but also provides a good grip on the machine.">}}
|
||||
|
||||
## Performance
|
||||
|
||||
Compared to the old T480s, the performance gain of the Intel Core Ultra and the
|
||||
dedicated NVIDIA GPU is very noticeable. Whether I compile R packages or analyze
|
||||
clinical data with ~80k subjects in [RStudio][], develop RAW images in [Darktable][],
|
||||
or work with Office in a VirtualBox-hosted Windows machine, everything is very
|
||||
snappy. For instance, a typical RAW image is now processed in under 1 second, as
|
||||
opposed to ~10 seconds on the T480s.
|
||||
|
||||
The machine wakes from sleep (suspend to RAM) extremely quickly, I guess this is due to
|
||||
[novel suspend mechanisms][s3]? On the other hand, boot times are rather slow
|
||||
(34-40s on AC power, T480s on battery 31 s!!).
|
||||
|
||||
## Fan
|
||||
|
||||
The fans spin up quickly, but the noise is not unpleasant. Maybe I can tweak the
|
||||
fan control in order to have them spin up a little more lazily. But when I had both
|
||||
my old laptop and the new one side by side, I realized that the T480s' fan noise
|
||||
drowns the P14s' fan noise. Notably, the P14s was running on AC power, while the
|
||||
T480s ran on battery. In fact, even the T480s with built-in graphics had its fan
|
||||
running most of the time when I was working with it (academic work, researching,
|
||||
writing, data analysis etc.).
|
||||
|
||||
## Energy consumption
|
||||
|
||||
The P14s' battery has much more capacity than the T480s' one, 75 Wh vs. 42 Wh.
|
||||
However, with my normal work load, the battery drains rather quickly. The
|
||||
following screenshot shows the charge level over time as I sat outside,
|
||||
editing a manuscript with Word running in a virtual machine (VirtualBox
|
||||
with Windows 11 guest) and doing some internet research in a browser. The
|
||||
screen brightness was set to 100%. After some 3.5 hours, it's time for a
|
||||
break...
|
||||
|
||||
{{< figure src="p14s-battery-drain.png">}}
|
||||
|
||||
## Making the switch from Ubuntu to Fedora
|
||||
|
||||
When I downloaded the Fedora [KDE spin][], I was admittedly a bit anxious.
|
||||
I had been working with Ubuntu and KDE neon, which is based on Ubuntu,
|
||||
for many years, and I wondered if Fedora would be very different.
|
||||
|
||||
It's not.
|
||||
|
||||
The three things that are really different from my perspective:
|
||||
|
||||
- To install something on the command line, use `dnf` rather than `apt`:
|
||||
|
||||
```bash
|
||||
sudo dnf install good-stuff
|
||||
```
|
||||
|
||||
- Removable disks (USB drives) are mounted on `/run/media/<USER>` rather
|
||||
than `/media/<USER>`.
|
||||
- More up-to-date kernel and software
|
||||
|
||||
## Conclusion
|
||||
|
||||
All in all, I am quite happy with the P14s. In the past couple of weeks, it has
|
||||
already proven to be a reliable work horse, and this is what I need. The
|
||||
keyboard really should be better, but hey, life is not perfect, is it?
|
||||
|
||||
[Darktable]: https://darktable.org
|
||||
[Fedora]: https://fedoraproject.org/
|
||||
[KDE forum]: https://discuss.kde.org/t/unable-to-start-kde-neon-plasma-on-core-ultra-nvidia-rtx-500-ada/18578
|
||||
[KDE neon]: https://neon.kde.org
|
||||
[KDE plasma]: https://kde.org/plasma-desktop/
|
||||
[KDE spin]: https://fedoraproject.org/spins/
|
||||
[p14s-weight]: https://www.lenovo.com/us/en/p/laptops/thinkpad/thinkpadp/thinkpad-p14s-gen-5-(14-inch-intel)-mobile-workstation/21g2002cus#tech_specs
|
||||
[rstudio]: https://posit.co/products/open-source/rstudio
|
||||
[s3]: https://en.wikipedia.org/wiki/ACPI#S3
|
||||
[xltoolbox.net]: https://www.xltoolbox.net/blog/2018/08/exit-thinkpad-t430s-enter-thinkpad-t480s.html
|
After Width: | Height: | Size: 177 KiB |
After Width: | Height: | Size: 954 KiB |
After Width: | Height: | Size: 3.8 MiB |
@ -1,13 +1,15 @@
|
||||
services:
|
||||
build:
|
||||
image: klakegg/hugo:ext-alpine
|
||||
image: hugomods/hugo:latest
|
||||
command: hugo
|
||||
volumes:
|
||||
- ".:/src"
|
||||
user: 1000:1000
|
||||
server:
|
||||
image: klakegg/hugo:ext-alpine
|
||||
command: server
|
||||
image: hugomods/hugo:latest
|
||||
command: server --buildDrafts --buildFuture
|
||||
volumes:
|
||||
- ".:/src"
|
||||
ports:
|
||||
- "1313:1313"
|
||||
|
||||
- "127.0.0.1:1313:1313"
|
||||
user: 1000:1000
|
||||
|
16
layouts/partials/analytics.html
Normal file
@ -0,0 +1,16 @@
|
||||
<!-- Matomo -->
|
||||
<script>
|
||||
var _paq = window._paq = window._paq || [];
|
||||
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
|
||||
_paq.push(['trackPageView']);
|
||||
_paq.push(['enableLinkTracking']);
|
||||
(function() {
|
||||
var u="https://matomo.bovender.de/";
|
||||
_paq.push(['setTrackerUrl', u+'matomo.php']);
|
||||
_paq.push(['setSiteId', '1']);
|
||||
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
|
||||
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
|
||||
})();
|
||||
</script>
|
||||
<!-- End Matomo Code -->
|
||||
|
22
layouts/partials/posts_single_info.html
Normal file
@ -0,0 +1,22 @@
|
||||
{{- with .Params.description }}<p>{{.}}</p>{{- end }}
|
||||
{{- if and .Params.author .Params.authorLink}}{{ $relreflink := relref . .Params.authorLink }}<p>{{ partial "svg.html" (dict "context" . "name" "author") }}<a href="{{ $relreflink }}" target="_blank">{{ .Params.author }}</a></p>
|
||||
{{- else if .Params.author }}{{ $relreflink := relref . .Site.Params.author.about }}<p>{{ partial "svg.html" (dict "context" . "name" "author") }}<a href="{{ $relreflink }}" target="_blank">{{ .Params.author }}</a></p>
|
||||
{{- else }}{{ $relreflink := relref . .Site.Params.author.about }}<p>{{ partial "svg.html" (dict "context" . "name" "author") }}<a href="{{ $relreflink }}" target="_blank">{{ .Site.Params.author.name }}</a></p>
|
||||
{{- end }}
|
||||
{{- with .Params.tags }}
|
||||
<p>{{- partial "svg.html" (dict "context" . "name" "posts_single_tags") -}}{{- range . -}}<span class="tag"><a href="{{ "tags/" | absLangURL }}{{ . | urlize }}">{{.}}</a></span>{{- end }}</p>
|
||||
{{- end }}
|
||||
{{- with .Params.categories }}
|
||||
<p>{{- partial "svg.html" (dict "context" . "name" "posts_single_categories") -}}{{- range . -}}<span class="category"><a href="{{ "categories/" | absLangURL }}{{ . | urlize }}">{{.}}</a></span>{{- end }}</p>
|
||||
{{- end }}
|
||||
<p>{{- partial "svg.html" (dict "context" . "name" "posts_single_date") }}{{ dateFormat .Site.Params.dateformNumTime .Date.Local -}}
|
||||
{{- if and (not (eq .Page.Params.ShowLastmod nil)) (.Page.Params.ShowLastmod) -}}
|
||||
{{- if and .GitInfo .Site.Params.gitUrl -}}
|
||||
[{{- partial "svg.html" (dict "context" . "name" "posts_single_git_commit") -}}<a href="{{ .Site.Params.gitUrl -}}{{ .GitInfo.Hash }}" target="_blank" rel="noopener">{{ .GitInfo.AbbreviatedHash -}}</a> @ {{ dateFormat .Site.Params.dateformNum .GitInfo.AuthorDate.Local -}}]
|
||||
{{- else if not (eq .Lastmod .Date ) -}}
|
||||
[{{.Site.Params.initialPublish | default "Initial Published on : "}} {{ dateFormat .Site.Params.dateformNumTime .Lastmod.Local -}}]
|
||||
{{- else -}}
|
||||
{{ errorf "Lastmod is not found in Page Frontmatter or Lastmod is same as Date" }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
</p>
|
37
layouts/partials/social-share.html
Normal file
@ -0,0 +1,37 @@
|
||||
<button id="share-btn" class="hdr-btn" title="{{i18n "share"}}">{{- partial "svg.html" (dict "context" . "name" "share") -}}</button>
|
||||
|
||||
<div id="share-links" class="animated fast">
|
||||
{{ $title := .Title }}
|
||||
{{ $url := printf "%s" .Permalink }}
|
||||
{{ $author := (.Params.author | default .Site.Params.author.name) }}
|
||||
{{ $summary := print $title ", by " $author "\n\n" .Params.description "\n" }}
|
||||
<ul>
|
||||
<li>
|
||||
<a href="#" rel="noreferrer noopener"
|
||||
target="mastodon"
|
||||
data-prompt="Please tell me your Mastodon instance"
|
||||
data-edittext="✏️"
|
||||
data-editlabel="Edit your Mastodon instance"
|
||||
class="mastodon-share">
|
||||
Share to Mastodon
|
||||
</a>
|
||||
{{ $mastodon_share := resources.Get "js/mastodon-share.js" | js.Build "mastodon-share.js" }}
|
||||
<script src="{{ $mastodon_share.RelPermalink }}" defer></script>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/intent/tweet?hashtags=hermit2&url={{ .Permalink }}&text={{ .Title }}" target="_blank" rel="noopener" aria-label="Share on X">{{- partial "svg.html" (dict "context" . "name" "x") -}}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://facebook.com/sharer/sharer.php?u={{ .Permalink }}" target="_blank" rel="noopener" aria-label="Share on Facebook">{{- partial "svg.html" (dict "context" . "name" "facebook") -}}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="mailto:?subject={{ .Title }}&body={{ .Permalink }}" target="_self" rel="noopener" aria-label="Share on Email">{{- partial "svg.html" (dict "context" . "name" "email") -}}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.linkedin.com/shareArticle?mini=true&url={{ $url }}&source={{ .Site.BaseURL }}&title={{ $title }}&summary={{ $summary }}" target="_blank" rel="noopener" aria-label="Share on LinkedIn">{{- partial "svg.html" (dict "context" . "name" "linkedin") -}}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" onclick="linkShare({{ $title }},{{ $url }},{{ $summary }}); return false;" target="_self" rel="noopener" aria-label="Copy Link">{{- partial "svg.html" (dict "context" . "name" "share_2") -}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
38
layouts/shortcodes/figure.html
Normal file
@ -0,0 +1,38 @@
|
||||
<figure{{ with .Get "class" }} class="{{ . }}"{{ end }}>
|
||||
{{- if .Get "link" -}}
|
||||
<a href="{{ .Get "link" }}"{{ with .Get "target" }} target="{{ . }}"{{ end }}{{ with .Get "rel" }} rel="{{ . }}"{{ end }}>
|
||||
{{- end -}}
|
||||
|
||||
{{- $u := urls.Parse (.Get "src") -}}
|
||||
{{- $src := $u.String -}}
|
||||
{{- if not $u.IsAbs -}}
|
||||
{{- with or (.Page.Resources.Get $u.Path) (resources.Get $u.Path) -}}
|
||||
{{- $src = .RelPermalink -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
<img src="{{ $src }}"
|
||||
{{- if or (.Get "alt") (.Get "caption") }}
|
||||
alt="{{ with .Get "alt" }}{{ . }}{{ else }}{{ .Get "caption" | markdownify| plainify }}{{ end }}"
|
||||
{{- end -}}
|
||||
{{- with .Get "width" }} width="{{ . }}"{{ end -}}
|
||||
{{- with .Get "height" }} height="{{ . }}"{{ end -}}
|
||||
{{- with .Get "loading" }} loading="{{ . }}"{{ end -}}
|
||||
><!-- Closing img tag -->
|
||||
{{- if .Get "link" }}</a>{{ end -}}
|
||||
{{- if or (or (.Get "title") (.Get "caption")) (.Get "attr") -}}
|
||||
<figcaption>
|
||||
{{ with (.Get "title") -}}
|
||||
<h4>{{ . }}</h4>
|
||||
{{- end -}}
|
||||
{{- if or (.Get "caption") (.Get "attr") -}}<p>
|
||||
{{- .Get "caption" | markdownify -}}
|
||||
{{- with .Get "attrlink" }}
|
||||
<a href="{{ . }}">
|
||||
{{- end -}}
|
||||
{{- .Get "attr" | markdownify -}}
|
||||
{{- if .Get "attrlink" }}</a>{{ end }}</p>
|
||||
{{- end }}
|
||||
</figcaption>
|
||||
{{- end }}
|
||||
</figure>
|
@ -1 +0,0 @@
|
||||
{"Target":"css/style.min.3b715be5bd264701c0fc591b2c4a36421d10ed026ad15fcf6d2f91991d4a77a7.css","MediaType":"text/css","Data":{"Integrity":"sha256-O3Fb5b0mRwHA/FkbLEo2Qh0Q7QJq0V/PbS+RmR1Kd6c="}}
|
5
update-blog.sh
Executable file
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
pushd /home/daniel/local/Code/blog
|
||||
docker compose up build && rsync -av --delete public/* bovender.de:/var/www/bovender/
|
||||
popd
|
||||
|