Signed-off-by: Magic_RB <magic_rb@redalder.org>
This commit is contained in:
Magic_RB 2021-03-04 17:22:33 +01:00
parent 35c8893dc8
commit 6b441371bf
No known key found for this signature in database
GPG key ID: 08D5287CC5DDCA0E
6 changed files with 256 additions and 40 deletions

View file

@ -1,5 +1,14 @@
@font-face {
font-family: "Ubuntu Medium";
src: url(/ttf/ubuntu-medium.ttf) format("truetype");
}
* {
font-family: "monospace";
font-family: "Ubuntu Medium";
}
ul {
padding: 0 0 0 1rem;
}
code {
@ -7,3 +16,45 @@ code {
background: #ACACAC;
padding: 0.1rem;
}
#table-of-contents {
position: sticky;
top: 0;
}
#content :is(h1, h2, h3, h4, h5, h6) {
display: inline;
border-bottom: 0.15rem solid #165578;
width: 100%;
padding-bottom: 0.1rem;
line-height: 1.75em;
}
#organizer {
display: flex;
flex-direction: column;
}
#content p {
flex-basis: auto;
text-align: justify;
text-justify: inter-word;
}
.sidebar {
flex-basis: auto;
}
@media only screen and (min-width: 768px) {
#organizer {
flex-direction: row;
}
#content {
flex-basis: 80%;
}
.sidebar {
flex-basis: 10%;
}
}

Binary file not shown.

View file

@ -1,6 +1,5 @@
#+TITLE: Emacs, the Journey to an Operating System
* Emacs, the Journey to an Operating System
** The Age without Emacs
* The Age without Emacs
It's the 12th of February, I'm playing Factorio on my laptop, when the bell rings and not long
after my Biology teacher enters the classroom, I quickly save and exit out of Factorio. After the
usual formalities I sit down and open my editor, so that I can take notes during the lesson. As
@ -17,11 +16,11 @@
and how painful my existence was. Let's go over the different pain points I now, in retrospect,
realize existed.
*** The Pain
** The Pain
If you're an Emacs veteran, you surely have already noticed everything I'll point out in the
next few paragraphs, but please do read on as I present my unique view on the issues.
**** Multiple Editors
*** Multiple Editors
Let's start with the most obvious one, during "A day in the Life of Me", I would switch between
3 different editors, being, in increasing order of time spent in each, VSCode, CLion and Vim.
This brings with it many issues, including but not limited to: keybindings, plugins/addons,

View file

@ -0,0 +1,79 @@
#+TITLE: On Docker Databases and Nixos
While learning Hashicorp Nomad+Vault+Consul, I decided that I'd convert all the Docker containers I use currently,
into their Nix-ified forms. In other words, I'd rewrite the ones I had, but I'd based them on NixOS, a truly
declarative enviroment, unlike /ehm/ all the other base images... Well, I didn't realize how *hard* it is to
"dockerize" databases, databases are inherently programs, which deal almost exclusively with state, as opposed to Nix
and Docker, which are both declarative systems (one of them is trying and failing really hard).
** Configuration
Configuration is a rather big part of what systems administrator(DevOps engineer for the cool kids) does, one must
correctly configure a program, most of the time dynamically. And because this is such an important thing, it baffles
me, why 90% of all containers primarily use and support environment variables. I get that it's a convenient way to do
it, it's simple widely supported, uniform, all around great, but *really* cumbersome. Say your config file looks like
this:
#+BEGIN_SRC conf
# stripped down Gitea configuration, I kept the parts that nicely illustrate my point
[server]
APP_DATA_PATH = /data/gitea
ROOT_URL = https://gitea.redalder.org/
DOMAIN = gitea.redalder.org
[database]
DB_TYPE = postgres
HOST = database-postgres
NAME = gitea
#+END_SRC
The config has two sections, =server= and =database=, each of these sections has =n= key-value pairs. This has
structure, it has multiple layers and configuration files can get much, much more complex than that. Now, for the
sake of argument, let's imagine that we want to "environment-ize" this config. The natural, and frankly only way to
do this is to essentially flatten the config file, so we'd get something like this:
#+BEGIN_SRC conf
SERVER_APP_DATA_PATH="/data/gitea"
SERVER_ROOT_URL="https://gitea.redalder.org/"
SERVER_DOMAIN="gitea.redalder.org"
DATABASE_DB_TYPE="postgres"
DATABASE_HOST="database-postgres"
DATABASE_NAME="gitea"
#+END_SRC
Now, you might think that this is completely fine, even reasonable, but let me explain to you why that is horrible.
First of, there is no imposed structure and structure is always good, nothing is preventing you from mixing the
=server= and =database= sections and while a "good" admin should not do that, it's best if they don't even have the
ability. Next depending on the parser, which parses this "configuration", you might encounter issues when you leave
out =""=, some are better at this than others, but once again, it's an implicit rule, which is bad. I hope you're
starting to understand the bigger picture, implicitness is *bad*, period. It introduces unnecessary mistakes that
could have been avoided if just the computer yelled at you. So why not give it the option to do that?
** Configuration and Databases
Now, it's finally time to combine databases with configuration. What we get is an all out war between immutable,
declarative environments holding stateful and infinitely changing data. You must make sure that your configuration
gets applied only at first start, so you must keep state yourself! In a Docker container! Madness! Then comes the
joy of updating the configuration. Say you give your user the option to specify the default authentication method
([[https://hub.docker.com/_/postgres][PostgreSQL]]), the user specifies that they want =scram-sha-256=, that's nice and all, so you apply it, but *only* on
the first boot. Why? Because now that the value is in the config file, if the user changed it, you'd have to figure
out *if* they changed it and then update the configuration file and that's really hard. The user might have gone into
where they store the state for PostgreSQL and manually changed the config file, they might have even completely
deleted your configuration and replaced it with their own? What should you do? Most Docker containers just take the
easy way out and do as PostgreSQL does and I don't blame them, there is nothing really that you can do.
** Nix - The Solution?
Similar to some good literature, this rant has gone full circle. We're back at the start, back on the topic of
Nix. How can Nix save us? By removing unnecessary state. The mutable configuration file? Gone, it's immutable
now. Not knowing whether a setting changed? Poof, gone too, Nix is fully declarative, which means it identifies
*everything* by a sha256 hash in addition to its developer configured name. Nix also serves as a single point of
truth, which means even if the user modifies the config files, they will be overwritten before they are used
again. This makes mix ups are impossible. Messy and flat "configuration" files? Solved too, the Nix expression language can be
as flat or as deep as you need it to be, you can create complex APIs with functions and all that jazz. Basically Nix
is awesome!
** Conclusion
The take-away from this rant, is that the best course of action is to figure out either how to completely replace
Docker and all the other container runtimes with something based on Nix, but since I'm a realist, I propose another
possible solution. We must get Nix to nicely work with Docker, so instead of clumsy environment variables, you'd
write your configuration in the form of Nix expressions and build a new docker image based on one common base. This
ensure that all configuration would be properly hashed and declarative, while allowing for much more complex config
files than environment variables or even templates.

92
make.el
View file

@ -5,11 +5,101 @@
;;; Code:
(load-file "./org-thtml/ox-thtml.el")
(require 'org)
(require 'ox)
(require 'ox-html)
(dolist (d '("public_html"))
(unless (file-exists-p d)
(make-directory d)))
;; https://alhassy.github.io/AlBasmala.html#Floating-TOC
(advice-add 'org-html--translate :before-until 'display-toc-as-toc)
(defun display-toc-as-toc (phrase info)
(when (equal phrase "Table of Contents")
"<a>
TOC
</a>"))
;; https://github.com/alphapapa/unpackaged.el#export-to-html-with-useful-anchors
(advice-add #'org-export-get-reference :override #'unpackaged/org-export-get-reference)
(defun unpackaged/org-export-get-reference (datum info)
"Like `org-export-get-reference', except uses heading titles instead of random numbers."
(let ((cache (plist-get info :internal-references)))
(or (car (rassq datum cache))
(let* ((crossrefs (plist-get info :crossrefs))
(cells (org-export-search-cells datum))
;; Preserve any pre-existing association between
;; a search cell and a reference, i.e., when some
;; previously published document referenced a location
;; within current file (see
;; `org-publish-resolve-external-link').
;;
;; However, there is no guarantee that search cells are
;; unique, e.g., there might be duplicate custom ID or
;; two headings with the same title in the file.
;;
;; As a consequence, before re-using any reference to
;; an element or object, we check that it doesn't refer
;; to a previous element or object.
(new (or (cl-some
(lambda (cell)
(let ((stored (cdr (assoc cell crossrefs))))
(when stored
(let ((old (org-export-format-reference stored)))
(and (not (assoc old cache)) stored)))))
cells)
(when (org-element-property :raw-value datum)
;; Heading with a title
(unpackaged/org-export-new-title-reference datum cache))
;; NOTE: This probably breaks some Org Export
;; feature, but if it does what I need, fine.
(org-export-format-reference
(org-export-new-reference cache))))
(reference-string new))
;; Cache contains both data already associated to
;; a reference and in-use internal references, so as to make
;; unique references.
(dolist (cell cells) (push (cons cell new) cache))
;; Retain a direct association between reference string and
;; DATUM since (1) not every object or element can be given
;; a search cell (2) it permits quick lookup.
(push (cons reference-string datum) cache)
(plist-put info :internal-references cache)
reference-string))))
(defun unpackaged/org-export-new-title-reference (datum cache)
"Return new reference for DATUM that is unique in CACHE."
(cl-macrolet ((inc-suffixf (place)
`(progn
(string-match (rx bos
(minimal-match (group (1+ anything)))
(optional "--" (group (1+ digit)))
eos)
,place)
;; HACK: `s1' instead of a gensym.
(-let* (((s1 suffix) (list (match-string 1 ,place)
(match-string 2 ,place)))
(suffix (if suffix
(string-to-number suffix)
0)))
(setf ,place (format "%s--%s" s1 (cl-incf suffix)))))))
(let* ((title (org-element-property :raw-value datum))
(ref (url-hexify-string (substring-no-properties title)))
(parent (org-element-property :parent datum)))
(while (--any (equal ref (car it))
cache)
;; Title not unique: make it so.
(if parent
;; Append ancestor title.
(setf title (concat (org-element-property :raw-value parent)
"--" title)
ref (url-hexify-string (substring-no-properties title))
parent (org-element-property :parent parent))
;; No more ancestors: add and increment a number.
(inc-suffixf ref)))
ref)))
(defvar org-publish-project-alist)
(setq org-publish-project-alist
`(("blog-org"
@ -28,7 +118,7 @@
:base-directory ,(expand-file-name "assets/")
:publishing-directory ,(expand-file-name "public_html/")
:recursive t
:base-extension "\\(jpg\\|gif\\|png\\|css\\|js\\|el\\|nb\\|ipynb\\|pdf\\|xml\\)"
:base-extension "\\(ttf\\|jpg\\|gif\\|png\\|css\\|js\\|el\\|nb\\|ipynb\\|pdf\\|xml\\)"
:publishing-function org-publish-attachment)
("blog"
:components ("blog-org" "blog-assets"))))

View file

@ -2,17 +2,14 @@
<html lang="en">
{{:include "head.html"}}
<body>
<div id="layout" class="pure-g">
<div class="content pure-u-1 pure-u-md-2-3">
<div id="organizer">
<div class="sidebar">{{org-html-toc 2 info}}</div>
<div id="content">
{{:if with-title}}<h1>{{title}}</h1>{{:endif}}
{{:if date}}<div class="post-meta">Published on {{format-time-string "%b %d, %Y" date}}</div>{{:endif}}
{{contents}}
</div>
</div>
<div class="sidebar"></div>
</div>
</body>
</html>