LEdoian's Bloghttps://blog.ledoian.cz/2024-02-17T16:55:00+01:00How to convert CBZ to PDF2024-02-17T16:55:00+01:002024-02-17T16:55:00+01:00LEdoiantag:blog.ledoian.cz,2024-02-17:/cbz-to-pdf.html<ol class="arabic simple"> <li>Extract the archive (cbz is just a zip, cbr is a rar, …)</li> <li><dl class="first docutils"> <dt>Convert individual pictures to PDF using <tt class="docutils literal">img2pdf</tt></dt> <dd><ul class="first last"> <li>Many other ways including <tt class="docutils literal">convert</tt> from ImageMagick tend to do weird stuff like breaking aspect ratios or adding margins</li> </ul> </dd> </dl> </li> <li>Merge files into the single PDF, e.g. using <tt class="docutils literal">qpdf <span class="pre">--empty</span> <span class="pre">--pages …</span></tt></li></ol><ol class="arabic simple"> <li>Extract the archive (cbz is just a zip, cbr is a rar, …)</li> <li><dl class="first docutils"> <dt>Convert individual pictures to PDF using <tt class="docutils literal">img2pdf</tt></dt> <dd><ul class="first last"> <li>Many other ways including <tt class="docutils literal">convert</tt> from ImageMagick tend to do weird stuff like breaking aspect ratios or adding margins</li> </ul> </dd> </dl> </li> <li>Merge files into the single PDF, e.g. using <tt class="docutils literal">qpdf <span class="pre">--empty</span> <span class="pre">--pages</span> *.pdf <span class="pre">--</span> output.pdf</tt>.</li> </ol> <div class="section" id="references"> <h2>References</h2> <ul class="simple"> <li><a class="reference external" href="https://askubuntu.com/questions/207172/how-to-convert-cbr-to-pdf">https://askubuntu.com/questions/207172/how-to-convert-cbr-to-pdf</a></li> <li><a class="reference external" href="https://superuser.com/questions/497293/how-to-convert-calibre-cbr-to-pdf-format-in-linux">https://superuser.com/questions/497293/how-to-convert-calibre-cbr-to-pdf-format-in-linux</a></li> </ul> </div> <div class="section" id="why"> <h2>Why</h2> <p>My eBook reader (PocketBook Touch Lux) does not seem to be able to handle cbz.</p> </div> Do not forget about IPv6 DNS2024-01-24T03:20:00+01:002024-01-24T03:20:00+01:00LEdoiantag:blog.ledoian.cz,2024-01-24:/forgetting-dns6.html<p>Do you think IPv6-only internet works OK? I am going to tell you that it does not, but it is not immediately visible. TL;DR: The internet can be broken also by forgetting to add AAAA records of the <em>nameservers</em>. This creates IPv4 requirement for the resolving even when the …</p><p>Do you think IPv6-only internet works OK? I am going to tell you that it does not, but it is not immediately visible. TL;DR: The internet can be broken also by forgetting to add AAAA records of the <em>nameservers</em>. This creates IPv4 requirement for the resolving even when the target is reachable using IPv6.</p> <div class="section" id="quick-recap"> <h2>Quick recap</h2> <p>Connecting to a website is easy, right? You type in the name, you get the front page.</p> <div class="figure"> <object data="https://blog.ledoian.cz/images/forgetting-dns6/image1.svg" style="width: 50%;" type="image/svg+xml"></object> <p class="caption">This is a very naïve idea of connecting to a server.</p> </div> <p>OK, it is a bit harder: the computer needs an IP address, so we need to use this magic box called DNS. The flow looks something like this:</p> <div class="figure"> <object data="https://blog.ledoian.cz/images/forgetting-dns6/image2.svg" style="width: 50%;" type="image/svg+xml"></object> <p class="caption">Slightly better, now we at least know the machine-readable address.</p> </div> <p>And for IPv6-only everything on the picture has to have IPv6 connectivity and AAAA DNS records.</p> <div class="section" id="reaching-ipv4-land-from-ipv6-only"> <h3>Reaching IPv4 land from IPv6-only</h3> <p>There are few^H^H^Hmany sites that still only support IPv4. To reach them, we need someone who can reach both the IPv4- and IPv6-land to go there on our behalf – a proxy. This proxy can be ad-hoc (I often use <tt class="docutils literal">ssh <span class="pre">-D</span></tt>) or there are well-known protocols like NAT64 with DNS64 to do that in a standard and lightweight manner. <a class="footnote-reference" href="#nat44" id="footnote-reference-1">[1]</a> In that case, the connection looks like this:</p> <div class="figure"> <object data="https://blog.ledoian.cz/images/forgetting-dns6/image3.svg" style="width: 100%;" type="image/svg+xml"></object> <p class="caption">And now we can reach the whole internet.</p> </div> <p>You might already know that you need some workaround like this to reach GitHub. What I think you might not know, you need similar workaround to reach the Wikipedia.</p> <p>Disclaimer: I like Wikipedia and this is not meant to shame them, just use as an example. I am aware of several other sites suffering from the same problem, including at least one IPv6 test. <a class="footnote-reference" href="#test-aaaa" id="footnote-reference-2">[2]</a> (It would be nice if they added the missing piece in the puzzle, though.)</p> </div> </div> <div class="section" id="enter-dns"> <h2>Enter DNS</h2> <p>Our picture has one unexplored magic box: the DNS. As per the definition (which I just made up and was not bothered to even fully formulate):</p> <blockquote> yada yada distributed database of records attached to the strings – domain names. The records hold various information about the domain depending on the type.</blockquote> <p>There are three interesting types of records: A records give IPv4 addresses, AAAA give IPv6 addresses and NS give names of servers who know about the particular subtree of the database. And to actually resolve the final AAAA record the (recursive) resolver starts at the <em>root zone</em> and tries to find the answer. <a class="footnote-reference" href="#dns-simplification" id="footnote-reference-3">[3]</a> The resolution algorithm can be visualised like this:</p> <div class="figure"> <object data="https://blog.ledoian.cz/images/forgetting-dns6/image4.svg" style="width: 100%;" type="image/svg+xml"></object> <p class="caption">Yeah, it's a mess.</p> </div> <p>There is one extra tricky bit: the NS records contain <em>names</em>, not addresses, so when resolving we need <em>two</em> queries for each layer (very simplified): first we ask for the final domain (<tt class="docutils literal">blog.ledoian.cz</tt>) and get a NS record (when the server does not have the answer) and then we need to ask for the A or AAAA record of the name from that record, so that we can connect to the server mentioned in the NS record. (This allows a nameserver to be made redundant and/or reside on other types of network.)</p> <p>You might start to see the issue. When the DNS was just a black box, we could paint the whole picture green and call it a day. And from the regular user's point of view, that is the case, just use some public DNS like 1.1.1.1, 8.8.8.8 or 9.9.9.9. Oh, right, I meant these easy-to-remember addresses: 2606:4700:4700::1111, 2001:4860:4860::8888 and 2620:fe::fe, respectively. The point is, they will give you the answer because they are dual-stack, not IPv6-only.</p> <p>In a way, those servers (or other dual-stack resolvers) act like another proxy, similar to the SSH, NAT64 and NAT44 ones mentioned earlier. This may not be much of a problem for many people. But if you have any reason to use your own recursive DNS server (privacy reasons, DNSSEC validation, ISP provides bad service, you are the ISP, …) <em>inside</em> an IPv6-only network, you <em>will</em> have issues. <a class="footnote-reference" href="#dns-behind-nat64" id="footnote-reference-4">[4]</a></p> </div> <div class="section" id="example-wikipedia"> <h2>Example: Wikipedia</h2> <p>Let's now see this in action. You know Wikipedia, right? And you can reach Wikipedia on IPv6, right? It has an AAAA record (don't mind the CNAME, that means that the server is really called some other way):</p> <pre class="literal-block"> $ dig en.wikipedia.org AAAA […] en.wikipedia.org. 18737 IN CNAME dyna.wikimedia.org. dyna.wikimedia.org. 323 IN AAAA 2a02:ec80:600:ed1a::1 </pre> <p>And this record does work:</p> <pre class="literal-block"> $ ncat --ssl 2a02:ec80:600:ed1a::1 443 &lt;&lt;GO GET /wiki/Main_Page HTTP/1.1 Host: en.wikipedia.org GO HTTP/1.1 200 OK […] content-language: en content-type: text/html; charset=UTF-8 content-length: 98078 &lt;!DOCTYPE html&gt; […] </pre> <p>But we can dig deeper: let's see what servers we are really asking:</p> <pre class="literal-block"> $ dig en.wikipedia.org AAAA +trace ; &lt;&lt;&gt;&gt; DiG … &lt;&lt;&gt;&gt; en.wikipedia.org AAAA +trace ;; global options: +cmd . 78918 IN NS e.root-servers.net. . 78918 IN NS f.root-servers.net. . 78918 IN NS g.root-servers.net. . 78918 IN NS h.root-servers.net. . 78918 IN NS i.root-servers.net. . 78918 IN NS j.root-servers.net. . 78918 IN NS k.root-servers.net. . 78918 IN NS l.root-servers.net. . 78918 IN NS m.root-servers.net. . 78918 IN NS a.root-servers.net. . 78918 IN NS b.root-servers.net. . 78918 IN NS c.root-servers.net. . 78918 IN NS d.root-servers.net. ;; Received 525 bytes from … in 0 ms org. 172800 IN NS c0.org.afilias-nst.info. org. 172800 IN NS a2.org.afilias-nst.info. org. 172800 IN NS a0.org.afilias-nst.info. org. 172800 IN NS b0.org.afilias-nst.org. org. 172800 IN NS b2.org.afilias-nst.org. org. 172800 IN NS d0.org.afilias-nst.org. ;; Received 788 bytes from 202.12.27.33#53(m.root-servers.net) in 24 ms wikipedia.org. 3600 IN NS ns0.wikimedia.org. wikipedia.org. 3600 IN NS ns1.wikimedia.org. wikipedia.org. 3600 IN NS ns2.wikimedia.org. ;; Received 658 bytes from 2001:500:48::1#53(b2.org.afilias-nst.org) in 20 ms en.wikipedia.org. 86400 IN CNAME dyna.wikimedia.org. ;; Received 94 bytes from 208.80.153.231#53(ns1.wikimedia.org) in 132 ms </pre> <p>Hey, there are IPv4 addresses in there! I know, this is cheating, the output is from a dual-stack machine. But we can still simulate IPv6-only resolution by adding <tt class="docutils literal"><span class="pre">-6</span></tt> flag:</p> <pre class="literal-block"> $ dig en.wikipedia.org AAAA +trace -6 ; &lt;&lt;&gt;&gt; DiG … &lt;&lt;&gt;&gt; en.wikipedia.org AAAA +trace -6 ;; global options: +cmd . 78915 IN NS d.root-servers.net. . 78915 IN NS e.root-servers.net. . 78915 IN NS f.root-servers.net. . 78915 IN NS g.root-servers.net. . 78915 IN NS h.root-servers.net. . 78915 IN NS i.root-servers.net. . 78915 IN NS j.root-servers.net. . 78915 IN NS k.root-servers.net. . 78915 IN NS l.root-servers.net. . 78915 IN NS m.root-servers.net. . 78915 IN NS a.root-servers.net. . 78915 IN NS b.root-servers.net. . 78915 IN NS c.root-servers.net. ;; Received 525 bytes from … in 0 ms org. 172800 IN NS d0.org.afilias-nst.org. org. 172800 IN NS c0.org.afilias-nst.info. org. 172800 IN NS b2.org.afilias-nst.org. org. 172800 IN NS a0.org.afilias-nst.info. org. 172800 IN NS b0.org.afilias-nst.org. org. 172800 IN NS a2.org.afilias-nst.info. ;; Received 816 bytes from 2001:500:2::c#53(c.root-servers.net) in 8 ms wikipedia.org. 3600 IN NS ns0.wikimedia.org. wikipedia.org. 3600 IN NS ns1.wikimedia.org. wikipedia.org. 3600 IN NS ns2.wikimedia.org. couldn't get address for 'ns0.wikimedia.org': not found couldn't get address for 'ns1.wikimedia.org': not found couldn't get address for 'ns2.wikimedia.org': not found dig: couldn't get address for 'ns0.wikimedia.org': no more </pre> <p>Some of those IPv4 addresses were benign – the respective servers are reachable both using IPv4 and IPv6 address or there is an alternative server that is reachable using IPv6. That is the case for the root nameserver – in the second case, we used C, which has IPv6 address (2001:500:2::c). In fact, the M server also has IPv6 address, but dig chose the IPv4 one (it should not matter):</p> <pre class="literal-block"> $ dig m.root-servers.net AAAA […] m.root-servers.net. 77991 IN AAAA 2001:dc3::35 </pre> <p>But the latter case is the bigger issue. For the domain <tt class="docutils literal">wikipedia.org</tt> there are three nameservers:</p> <pre class="literal-block"> $ dig wikipedia.org NS -6 […] wikipedia.org. 86400 IN NS ns0.wikimedia.org. wikipedia.org. 86400 IN NS ns1.wikimedia.org. wikipedia.org. 86400 IN NS ns2.wikimedia.org. </pre> <p>This is the last answer that we could get on an IPv6-only network, because none of these three servers has AAAA record (some of them may have IPv6 address unknown to us):</p> <pre class="literal-block"> $ dig ns0.wikimedia.org AAAA […] ;; Got answer: ;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 59468 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1 </pre> <p>The NOERROR status says the domain name exists, but we got zero answers for AAAA records. This is the case for all three nameservers. And here is the ultimate picture of what is happening and what goes wrong.</p> <div class="figure"> <object data="https://blog.ledoian.cz/images/forgetting-dns6/image5.svg" style="width: 100%;" type="image/svg+xml"></object> <p class="caption">The breakage in action</p> </div> <p>Also note that the connection from the laptop to the DNS resolver may in fact consist of a chain of several (caching, non-recursive) DNS resolvers, so that the final DNS resolver can have dual-stack connectivity.</p> </div> <div class="section" id="the-problems-with-this-state"> <h2>The problems with this state</h2> <p>So, what is the deal. We <em>just</em> need to have a dual-stack DNS resolver somewhere, and that's it, no? Well, yes but actually yes.</p> <p>There are two problems with this: First, this means that any new ISP needs to have <em>at least some</em> IPv4 address, even if they intend to just use IPv6 services. IPv4 addresses are scarce, <a class="reference external" href="https://blog.apnic.net/2021/12/16/opinion-ipv4-address-markets/">expensive</a> and small blocks <a class="reference external" href="https://labs.ripe.net/author/stephen_strowes/visibility-of-ipv4-and-ipv6-prefix-lengths-in-2019/">don't route well</a>, which is not great both from the new ISP's and from overal routing's point of view. It also hinders IPv6 deployment and postpones IPv4 abandonment, needlessly.</p> <p>The second issue is that this is not very visible. We are building IPv6 world, but deep inside it still relies on IPv4, which might lead to great surprise when we start cutting off IPv4 internet. And it might lead to false sense of having IPv6 deployed, which is not true to the whole extent.</p> <p>Insert &quot;It was DNS&quot; meme here.</p> </div> <div class="section" id="solution"> <h2>Solution</h2> <p>The solution of this state is simple: get IPv6 connectivity to your authoritative DNS server (or use another) and do not forget to add an AAAA record for it in DNS. If the DNS server already has IPv6 it is probably just a matter of adding a single line to the zone file (and a second one for the DNSSEC signature), which should not be a big deal.</p> <p>Unfortunately, this needs to be done for the whole DNS chain. Especially domain names at universities are infamous for very nested domains. A domain name may look like <tt class="docutils literal"><span class="pre">machine.department.location.faculty.university.some-common.suffix</span></tt>. That tree is deep and so is the resolution of this problem.</p> </div> <div class="section" id="amusing-bug-of-almost-good-deployment"> <h2>Amusing bug of almost good deployment</h2> <p>We have seen there may be multiple NS records for a domain and thus multiple nameservers. This is good for redundancy. But this does not mean that the servers will have the same records – they are only supposed to give equivalent answers (as far as I know).</p> <p>I have come across a silly misconfiguration: a domain which has several nameservers, which serve a <em>slightly</em> different set of NS records for its subdomain. Specifically, the servers which were only reachable using IPv4 were <em>exactly</em> the servers that knew about one additional nameserver for the subdomain, which, incidentally, was the <em>only</em> one that was IPv6-capable.</p> <p>So, while all the correct records were present in DNS (somewhat/somewhere), this still meant that IPv6-only resolution was doomed to fail because the IPv6 nameserver chain was broken. (This has already been fixed.)</p> <hr class="docutils" /> <table class="docutils footnote" frame="void" id="nat44" rules="none"> <colgroup><col class="label" /><col /></colgroup> <tbody valign="top"> <tr><td class="label"><a class="fn-backref" href="#footnote-reference-1">[1]</a></td><td>This is very much the same as when you try to reach the IPv4-public-land from IPv4-private-land, that is, from a private range of IP addresses. This is called either just NAT, or NAT44 to denote IPv4-to-IPv4 NAT.</td></tr> </tbody> </table> <table class="docutils footnote" frame="void" id="test-aaaa" rules="none"> <colgroup><col class="label" /><col /></colgroup> <tbody valign="top"> <tr><td class="label"><a class="fn-backref" href="#footnote-reference-2">[2]</a></td><td>There are several more tests that do not even have the AAAA record, lol.</td></tr> </tbody> </table> <table class="docutils footnote" frame="void" id="dns-simplification" rules="none"> <colgroup><col class="label" /><col /></colgroup> <tbody valign="top"> <tr><td class="label"><a class="fn-backref" href="#footnote-reference-3">[3]</a></td><td>In my example, there is a single recursive DNS resolver external to my machine in order not to complicate it too much. The real deployment is often trickier.</td></tr> </tbody> </table> <table class="docutils footnote" frame="void" id="dns-behind-nat64" rules="none"> <colgroup><col class="label" /><col /></colgroup> <tbody valign="top"> <tr><td class="label"><a class="fn-backref" href="#footnote-reference-4">[4]</a></td><td>I have not yet tried to run a recursive DNS in a network with DNS64 and NAT64. Could be fun :-D My wild guess is that I would need CLAT (i.e. the full 464XLAT deployment) to make that work, since the resolver is connecting directly to IPv4 addresses and would need to learn to use NAT64 to resolve them. (The CLAT could be built right into the resolver, though).</td></tr> </tbody> </table> </div> About this blog2024-01-10T16:47:00+01:002024-01-10T16:47:00+01:00LEdoiantag:blog.ledoian.cz,2024-01-10:/about-blog.html<p>This is my blog and this article describes its setup and other details about my intentions. The actual <a class="reference internal" href="#the-setup">setup</a> is probably the most interesting tech-wise.</p> <div class="section" id="what-is-this"> <h2>What is this?</h2> <p>My own space on the internet where I can post whatever and link others to it. It might end up containing rants …</p></div><p>This is my blog and this article describes its setup and other details about my intentions. The actual <a class="reference internal" href="#the-setup">setup</a> is probably the most interesting tech-wise.</p> <div class="section" id="what-is-this"> <h2>What is this?</h2> <p>My own space on the internet where I can post whatever and link others to it. It might end up containing rants, guides, ideas, or maybe nothing at all in the end. Only the future will tell.</p> <p>The blog might even serve as my personal web page/introduction. Maybe. Maybe not…</p> <p>The main motivation is to have low-effort way to post random stuff. Which leads to my requirements for this thing.</p> </div> <div class="section" id="requirements"> <h2>Requirements</h2> <p>(The requirements are a bit too idealistic, so not all of them were satisfied…)</p> <ul class="simple"> <li>low-effort, me-friendly, low-maintenance – I don't want to have to learn too many new technologies to use this. This includes the required technologies: Python, Markdown/reStructuredText, Jinja2, git, …</li> <li>Technical and math content ~~friendly~~ compatible – I expect that to appear here.</li> <li>Static site – for security, coolness factor and control. Also static on the front-end, because I don't like JavaScript and/or running untrusted code on my machine (even when in a sandbox). The SSG should likely be aimed at creating blogs, not documentation. Also, self-contained, as in not depending on third-party sites.</li> <li>No moving parts in the infrastructure (or as few as possible) – if it works on my machine, it should just get mirrored to the public site with as few modifications as possible.</li> <li>Transparent – I should be able to understand it, maybe others could also use it as a resource or take inspiration. (At one point, this deployment itself started being interesting, so if I can share the background as well as the final webpage, it would be cool.)</li> <li>Followable – I know you internet guys like to ~~stalk~~ follow people :-)</li> <li>Aligned with my values: minimalist, simple, extensible/hackable, FLOSS</li> <li>If the platform could distinguish translations and do strikethroughs, it would be nice, but that is not a hard requirement.</li> </ul> <p>There are several features of conventional blogs that I consider to be a non-goals or even anti-goals. Mostly it is about interactivity – I don't aim for having any kind of comments here, or really anything that would require JavaScript or complex HTML/CSS. And appearance goes past me as well, I instead try to let the browser decide how to display this page – more on that <a class="reference internal" href="#design-considerations">below</a>.</p> <p>The workflow I wanted to achieve is something like: Write the content, git it, build it (locally, no CI/CD), push it, done. Single write, single push, very simple.</p> <p>And I managed to achieve something like that, via learning (too much?) about git.</p> <!-- TODO: fix the worktree bug already! --> </div> <div class="section" id="the-setup"> <h2>The setup</h2> <p>Naturally for a sysadmin/netadmin, the setup consists of 7 ~~ISO/OSI~~ layers:</p> <ol class="arabic simple"> <li><strong>Physical layer</strong>: cheap Hetzner VPS. Not physical, but whatever.</li> <li><strong>Network layer</strong>: Nginx</li> <li><strong>Persistence layer</strong>: <a class="reference external" href="https://gitea.ledoian.cz/LEdoian/blog">this git repo</a>. I will elaborate below why can you see this both rendered here and in the source form in Forgejo.</li> <li><strong>Content layer</strong>: Markdown or reStructuredText files.</li> <li><strong>Business logic layer</strong>: <a class="reference external" href="https://getpelican.com">Pelican</a>. It's rather popular and written in Python, I didn't look further.</li> <li><strong>Presentation layer</strong>: I hacked my own theme, because I didn't like any in the <a class="reference external" href="https://github.com/getpelican/pelican-themes">pelican-themes repo</a>. I was a bit inspired by the layout of <a class="reference external" href="https://eev.ee/blog">eevee's blog</a>, but I wanted a dark theme. And as you can see, I can't do quality frontend, so it ended up horrible… :-D</li> <li><strong>Stalking layer</strong>: Pelican's built-in RSS and Atom feed generators. Not linked from anywhere at the moment, but <a class="reference external" href="https://gitea.ledoian.cz/LEdoian/blog/src/branch/blog/output/feeds">the repo will tell you</a> what hides under the <tt class="docutils literal">/feeds/</tt> path. Or you can utilize the repo (for personal use – the content's license is not decided at the moment)…</li> </ol> <p>Most of this is straightforward, the fancy part is my repo. The repo contains both source and rendered content, so that I can point Nginx right at a checkout and have Git solve both persistence and deployment without additional moving parts.</p> <p>There are two tricks in the configuration of Git repositories: pushing to a checked out repo is enabled by configuring <tt class="docutils literal">receive.denyCurrentBranch = updateInstead</tt> in the target repository (which is just a normal repo, not a bare one), and then I just told my source repositories <a class="footnote-reference" href="#multiple-src" id="footnote-reference-1">[1]</a> to use two push targets for the remote (the first line <em>replaces</em> the original push address for some reason):</p> <pre class="literal-block"> git remote set-url --add --push blog_remote gitea&#64;gitea.ledoian.cz:LEdoian/blog.git git remote set-url --add --push blog_remote blog_user&#64;blog.ledoian.cz:blog_dir </pre> <p>The blog user is just a user with SSH access via authorized keys, no special sauce there. Nginx is then pointed to serve <tt class="docutils literal">~blog_user/blog_dir/output/</tt> at <tt class="docutils literal">blog.ledoian.cz</tt>. (The <tt class="docutils literal"><span class="pre">git-remote(1)</span></tt> manpage requires me to have both repositories in sync, but as long as I configure all my repositories this way, I should be safe, and I think I could get away with my blog checkout getting behind accidentally.)</p> </div> <div class="section" id="my-workflow-and-lots-of-drafts"> <h2>My workflow and lots of drafts</h2> <p>It's Git so it's only natural for me to use various branches and repositories even for a dumb blog. There are in fact 4 stages an article may go through <a class="footnote-reference" href="#skipping-stages" id="footnote-reference-2">[2]</a>:</p> <ol class="arabic"> <li><p class="first">A private draft: lives on a branch <tt class="docutils literal">priv/something</tt>, may contain private infos (like when I would just copy-paste from terminal without redaction) and this branch will probably never be merged to the main repo. Nothing about these branches is guaranteed.</p> </li> <li><p class="first">A public WIP draft: uses a branch called <tt class="docutils literal">pub/something</tt> which is pushed to Forgejo (and in fact also to the blog itself, but that is just an implementation detail). The draft is either does not build or is very incomplete and I expect to add stuff in a way that could break the build, so I put it on a separate branch. The branch will be probably merged to the main branch (called <tt class="docutils literal">blog</tt>) when it is ready.</p> <p>The <tt class="docutils literal">pub/…</tt> branches can be created either manually or by cherry-picking from the respective <tt class="docutils literal">priv/…</tt> branch, but that will likely not be distinguishable. (I am too lazy to keep the references even in the commit logs.)</p> </li> <li><p class="first">When a draft is almost ready (or the content has simple syntax), it gets placed on the <tt class="docutils literal">blog</tt> branch. The only thing that designates it as a draft is <tt class="docutils literal">status: draft</tt> in the frontmatter, which means that the article will get rendered and put somewhere on the public blog, but not reachable from the title page (&quot;unlisted&quot;).</p> </li> <li><p class="first">Of course, eventually (and hopefully) the article gets published for everyone to see. At that point, it is complete (or at least that is what I thought when marking it as published). Possibly it might be updated in the future, but no such update is anticipated at the moment of publishing. <a class="footnote-reference" href="#update-this" id="footnote-reference-3">[3]</a></p> </li> </ol> <p>I use Git to synchronize my private branches among machines, so there are actually two &quot;server-side&quot; repositories (private and public one) and thus two remotes. <a class="footnote-reference" href="#private-branches-wish" id="footnote-reference-4">[4]</a></p> <p>As for the actual workflow, for the main branch it usually consists of: writing content, committing it, building the web, checking it locally, committing the built blog and pushing it. Sometimes I do the commits together, but I always separate the rendering/building commits from the content-creating ones, so that I can handle those differently if needed (i.e. there is no point in cherry-picking the built content, I can generate it). <a class="footnote-reference" href="#git-purists" id="footnote-reference-5">[5]</a></p> <p>For other branches I use some applicable subset of the steps above, probably.</p> </div> <div class="section" id="design-considerations"> <h2>Design considerations</h2> <p>The appearance of the blog is maybe not nice. That is for two reasons: I don't have the right idea about how to make it much better and I want to have a rather simple CSS for the web. The latter wish is because I tend to tweak appearance of sites I visit using my own styles, so I would like you to be able to do the same.</p> <p>And for the former reason, if you have any ideas / improvements (including user styles), hit me at <a class="reference external" href="mailto:blog&#64;pokemon.ledoian.cz">blog&#64;pokemon.ledoian.cz</a> :-)</p> <p>My overall idea is a dark-by-default <a class="footnote-reference" href="#light-theme" id="footnote-reference-6">[6]</a> minimalist page with a single menu on the right containig all the relevant links. The page should not dictate too much but rather let the user agent decide the rendering (<a class="reference external" href="https://html.spec.whatwg.org/multipage/rendering.html#rendering">it does anyway…</a>).</p> <p>I want my blog to render similarly in Gecko-, WebKit- and Blink-based browsers (e.g. Firefox, Badwolf, Qutebrowser). Others should be usable. Browser-/engine-specific styles are not welcome – let's keep it simple. And no JavaScript…</p> </div> <div class="section" id="work-in-progress-todos"> <h2>Work in progress / TODOs</h2> <p>This thing is at the moment very barebones, which is sufficient for the main purpose. However, I would like to have some features here, one day, hopefully:</p> <ul class="simple"> <li>Dates in the article headers (and maybe more improvements of the theme, see above)</li> <li>Stable category and tag names and a page with a description of them. As of now I haven't really invented a system of sorting my content, which leads to a mess… Please don't rely on categories having any particular name / URL for now.</li> <li>Link the RSS feeds from somewhere</li> <li>Personal info with links to my other profiles</li> <li>Some linking to the Fediverse and using it for comments (since there will be no comments here)</li> <li>Sensible translations, maybe (if I/someone ever get to write the same content again in a different language…)</li> <li>Improve the list of talks I've given (create some kind of sensible table maybe?)</li> <li>Decide on a licence for the content (If you want to utilize something here before I do that, please ask me, I think we can find a way :-))</li> </ul> <p>If you are so upset with this blog (or maybe bored) that you want to improve it, send me patches / ideas. I don't expect anyone to do that, though :-D (And I do not promise you that I will use the patch, even if it matches all my opinions above. I also have some gut feelings about what I like…)</p> <p>Also, tell me if you hate something else about my page. I want to at least know whom I upset :-D (but I will probably also think about your gripes and whether I can and should try to avoid them…)</p> <hr class="docutils" /> <table class="docutils footnote" frame="void" id="multiple-src" rules="none"> <colgroup><col class="label" /><col /></colgroup> <tbody valign="top"> <tr><td class="label"><a class="fn-backref" href="#footnote-reference-1">[1]</a></td><td>I also use multiple machines on which I can write stuff.</td></tr> </tbody> </table> <table class="docutils footnote" frame="void" id="skipping-stages" rules="none"> <colgroup><col class="label" /><col /></colgroup> <tbody valign="top"> <tr><td class="label"><a class="fn-backref" href="#footnote-reference-2">[2]</a></td><td><p class="first">I am lazy and chaotic (good), so the stages are optional and non-linear, and sometimes involve paper. This article is a prime example: parts of it were on two different private branches, but at the end I wrote it from scratch directly on the main branch. And the requirements were written on a paper originally.</p> <p class="last">Nevertheless, the general idea still holds and may inspire others, so it makes sense to keep this part in the article. (Also, this footnote might not make sense before reading the definition of the stages, but I didn't find a better place to put it…)</p> </td></tr> </tbody> </table> <table class="docutils footnote" frame="void" id="update-this" rules="none"> <colgroup><col class="label" /><col /></colgroup> <tbody valign="top"> <tr><td class="label"><a class="fn-backref" href="#footnote-reference-3">[3]</a></td><td>Well, given this article contains some future plans, I actually anticipate update of this one, but maybe not in the near future. So the outline is not really correct, but I make the rules :-) (There were some build breaks on the main branch, too :-D)</td></tr> </tbody> </table> <table class="docutils footnote" frame="void" id="private-branches-wish" rules="none"> <colgroup><col class="label" /><col /></colgroup> <tbody valign="top"> <tr><td class="label"><a class="fn-backref" href="#footnote-reference-4">[4]</a></td><td>I would love if my Forgejo could have &quot;private branches&quot;, but I understand that the overhead for doing this is not nice, since it would need to be able to decide for any object, whether it is public or not (you can do <tt class="docutils literal">git fetch &lt;remote&gt; <span class="pre">&lt;object-hash&gt;</span></tt>) and somehow keep track even with rebases, merges, force-pushes, many branches, … Having a separate private repository is not a big problem in comparison.</td></tr> </tbody> </table> <table class="docutils footnote" frame="void" id="git-purists" rules="none"> <colgroup><col class="label" /><col /></colgroup> <tbody valign="top"> <tr><td class="label"><a class="fn-backref" href="#footnote-reference-5">[5]</a></td><td>Git purists might want to tell me that committing build artifacts is not good practice. I know and I explicitly don't care in case of this repo, because here I prioritise my own comfort of being able to check everything locally and then be reasonably sure the deployed version will also work, all this with only a single push somewhere. Of course, one could argue that with that there is no reason to create two commits, but it does not really bother me to run something like <tt class="docutils literal">git commit <span class="pre">-m&quot;render&quot;</span> output/</tt> when I am sure it works, and this keeps readable diffs separate from the non-readable ones (i.e. the changes in generated HTML).</td></tr> </tbody> </table> <table class="docutils footnote" frame="void" id="light-theme" rules="none"> <colgroup><col class="label" /><col /></colgroup> <tbody valign="top"> <tr><td class="label"><a class="fn-backref" href="#footnote-reference-6">[6]</a></td><td>Having the page be dark-by-default is my preference, but I respect that others may prefer light sites. However, I have not yet determined what colors should be used (probably still cyan / blue / maybe purple-ish, but I don't know what shade) nor understood how to use <tt class="docutils literal"><span class="pre">&#64;media(prefers-color-scheme)</span></tt> in a maintainable and simple way (in the context of my theme). So naturally, this is postponed to the future…</td></tr> </tbody> </table> </div> Smršť 2023 (CZ)2023-12-02T18:00:00+01:002023-12-02T18:00:00+01:00LEdoiantag:blog.ledoian.cz,2023-12-02:/smrst2023-cs.html<p>Na <a class="reference external" href="https://ksp.mff.cuni.cz/akce/smrst/2023/">Smršti</a> jsem přednášel o distribuci SW a o technicky zajímavých železničních neštěstích.</p> <div class="section" id="materialy"> <h2>Materiály</h2> <ul class="simple"> <li><a class="reference external" href="https://blog.ledoian.cz/static/talks/smrst2023/talk.pdf">Slidy ke přednášce o neštěstích</a></li> </ul> <p>(Pozn.: Možná se ještě změní adresa téhle stránky, protože je to celé WIP…)</p> </div>