aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--TODO.md72
-rw-r--r--content/articles/site-backend.md34
-rw-r--r--content/posts/2006-03-19-openvpn-article-in-linux-magazine.html15
-rw-r--r--content/posts/2023-05-02-bookworm-and-podman.md2
-rw-r--r--content/posts/2023-12-02-firefox-redux.md21
-rw-r--r--content/posts/2025-05-18-onion-service-mirror.md22
-rw-r--r--content/posts/2025-06-07-uninstall-facebook.md132
-rw-r--r--content/posts/2025-06-08-armbian-on-odroid-n2l.md145
-rw-r--r--content/posts/2025-06-08-nginx-caching-and-security-headers.md27
-rw-r--r--content/posts/2025-06-08-old-openvpn-article.md36
-rw-r--r--content/posts/2025-10-04-polycvss-v0.2.0.md143
-rw-r--r--content/projects/polycvss.md10
-rw-r--r--data/projects.yaml5
-rw-r--r--static/files/articles/site-backend/pablotron.onion.conf.txt29
-rw-r--r--static/files/pabs.asc46
-rw-r--r--static/files/posts/armbian-on-odroid-n2l/n2l-1024.pngbin0 -> 516107 bytes
-rw-r--r--static/files/posts/armbian-on-odroid-n2l/n2l-1024.webpbin0 -> 71378 bytes
-rw-r--r--static/files/posts/armbian-on-odroid-n2l/n2l.jpgbin0 -> 5520816 bytes
-rw-r--r--static/files/posts/armbian-on-odroid-n2l/odroid-n2l-root_not_logged_in_yet.txt44
20 files changed, 723 insertions, 62 deletions
diff --git a/README.md b/README.md
index 59378cb..6aa9d08 100644
--- a/README.md
+++ b/README.md
@@ -105,7 +105,7 @@ Notes:
2. Use [`pngquant`][pngquant] to shrink [PNGs][png].
3. Use `gm convert -define web:lossless=true foo.{png,webp}`
to compress PNGs and convert them to `webp`s.
-4. Use `gm convert foo.{png,webp}`
+4. Use `gm convert foo.{jpg,webp}`
to compress JPEGs and convert them to to `webp`s.
5. Use the `pe-figure` shortcode for progressive enhanced `figure` tags
with a fallback image.
diff --git a/TODO.md b/TODO.md
index f7fd940..4f48455 100644
--- a/TODO.md
+++ b/TODO.md
@@ -15,12 +15,11 @@
- monthly link sweep?
- upgrade from bulma 0.9.3 to bulma 1.0.0
<https://bulma.io/documentation/start/migrating-to-v1/>
-- set up logrotate for more granular `goaccess` reports
-- vanity `pablotron*.onion` address (computing on `meh`)
- projects: better project pages (pull from `README.md`)
- wkd for pgp
- home: rename "Archived Posts..." to "Older Posts"
- archive: rename "Archived Posts..." to "Older Posts"
+- index with pagefind: (<https://pagefind.app/>, <https://www.tbray.org/ongoing/When/202x/2025/11/01/Blog-Search-Pagefind>)
## linting
- replace `<img>` in old posts with `{{< figure >}}` (partial work
@@ -48,6 +47,8 @@
- plug-in hybrids: find link about people mashing accelerators and
effective mpg being substantially lower than advertised
- lots of good stuff in "science/climate" bookmarks
+ - wind kills birds garbage:
+ <https://codingrelic.geekhold.com/2024/12/wind-turbines-and-bird-deaths.html>
- thoughts on "relevance of classic fuzz testing"
- https://neverworkintheory.org/2021/10/01/the-relevance-of-classic-fuzz-testing.html
- "law of small numbers": http://psychology.iresearchnet.com/social-psychology/decision-making/law-of-small-numbers/
@@ -145,6 +146,9 @@
<https://blog.tidelift.com/the-state-of-package-signing-across-package-managers>
- declarative install (go)
rationale: <https://blog.phylum.io/phylum-discovers-dozens-more-pypi-packages-attempting-to-deliver-w4sp-stealer-in-ongoing-supply-chain-attack>
+ - counterexamples:
+ - rubygems (arbitrary ruby)
+ - rust (arbitrary rust in `build.rs`)
- typosquatting (see sqo vulns from may email)
- starsquatting (requests, phpass): https://medium.com/checkmarx-security/typosquatting-attack-on-requests-one-of-the-most-popular-python-packages-3b0a329a892d
- ref: https://kerkour.com/rust-crate-backdoor
@@ -201,8 +205,6 @@
gambler's ruin (intro to prob, ch 3.5)
constant-time fibonacci
- fzf, ripgrep
-- https://krebsonsecurity.com/2022/08/the-security-pros-and-cons-of-using-email-aliases/
- (email aliases, suggest whitelist instead of blacklist)
- bad defaults ("knives up in dishwasher"):
- nullable in code/db (see also: <https://carlineng.com/?postid=sql-critique#blog>)
- mutable variables
@@ -225,12 +227,14 @@
https://github.com/gorhill/uBlock/wiki/Procedural-cosmetic-filters
<https://rubyweekly.com/issues/620>
##table.item:has(p.name > .tag-sponsor)
+ - dark reader
+ - tab stash
- hardening
- try out various lsms
- apparmor
- lockdown
- selinux
- - systemd hardening
+ - systemd hardening (examples: spamassassin config)
- owasp guides
- disa stigs
- dropping system calls (firejail)
@@ -238,6 +242,7 @@
- heat pump (pictures/heat-pump-20220930)
- <https://insideevs.com/news/509767/tesla-model3-control-arm-fix/>
- `curl|bash` is madness
+ - vulnerable to clickfix: <https://arstechnica.com/security/2025/11/clickfix-may-be-the-biggest-security-threat-your-family-has-never-heard-of/>
- gosec vs govulncheck
https://github.com/securego/gosec
https://www.pixelstech.net/article/1667102060-Secure-Your-Go-Code-With-Vulnerability-Check-Tool
@@ -256,9 +261,6 @@
- thoughts on tesla: <https://digbysblog.net/2022/11/27/elon-musk-remembered-for-tech-he-destroyed/>
- try out pgsodium:
<https://github.com/michelp/pgsodium>
-- aegis authenticator dance w/ tablet
- <https://github.com/beemdevelopment/Aegis>
- (including installing lineage 20)
- fix-enterprise-episodes.rb
- imagecompare (flex:git/go/test/imagecompare)
- don't expose ssh (imap)
@@ -293,6 +295,7 @@
- sorta: elasticsearch (opensearch), redis
- reddit, stackoverflow
- my tools
+ - hnb
- vim: (2 pragbooks vim books, vimhelp.org, learnvimthehardway)
- tried neovim, still like vim more
- irssi
@@ -333,6 +336,9 @@
- ollama
- btop (recommended by alonzo)
- goaccess: apache log reporting tool
+ - aegis authenticator dance w/ tablet
+ <https://github.com/beemdevelopment/Aegis>
+ (including installing lineage 20)
- compare signify, age, and minisign:
https://flak.tedunangst.com/post/signify
https://blog.gtank.cc/modern-alternatives-to-pgp/
@@ -351,7 +357,6 @@
- firefox terms of use nonsense
https://arstechnica.com/tech-policy/2025/02/firefox-deletes-promise-to-never-sell-personal-data-asks-users-not-to-panic/
https://lwn.net/Articles/1012430/
-- firefox tab groups (new in firefox 136)
- problems w/ tracking apis:
- orwellian name (does not preserve privacy)
- analogies for folks to understand correlation: clue, sudoku, wordle
@@ -474,6 +479,8 @@
- chatgpt <https://www.jwz.org/blog/2023/02/the-bullshit-fountain/>
- ai is not intelligence: <https://current.workingdirectory.net/posts/2023/enough-about-ai/>
- (lots of other stuff by ed zitron)
+ - "grift bubble":
+ <https://codingrelic.geekhold.com/2025/01/tale-of-two-crises-y2k-and-o3.html>
- pi cases (fish, lemon, and pumpkin, see pics on phone)
- transport-layer shenanigans:
- included in openssl 3.4 (phoronix article)
@@ -523,6 +530,8 @@
- run tails in gnome boxes with persistent storage
(see x1 notes for details, but it's `qemu-img convert ... qemu-img resize`)
ref: <https://unix.stackexchange.com/questions/517524/install-tails-with-persistent-storage-on-virtualbox>
+- signal in tails:
+ <https://bisco.org/notes/installing-and-running-signal-on-tails/>
- bot user-agent blocking:
<https://www.jwz.org/blog/2025/05/user-agent-blocking/#comment-259206>
<https://perishablepress.com/ultimate-ai-block-list/> (linked from comment)
@@ -553,17 +562,33 @@
"decrypt", "sign", "verify", etc
- still making sense of trust handling
- available in debian
-- armbian on odroid n2l
- (first login hiccups, root pw)
- (netplan hiccups)
- (see notes v4.txt)
+- privacy:
+ - mozilla "privacy preserving" garbage (above)
+ - https://krebsonsecurity.com/2022/08/the-security-pros-and-cons-of-using-email-aliases/
+ (email aliases, suggest whitelist instead of blacklist)
+ - web fingerprinting: <https://www.amiunique.org/fingerprint>
+ eff coveryourtracks: <https://coveryourtracks.eff.org/>
+ - eff surveillance self-defense: <https://ssd.eff.org/>
+ - msn good article about facebook snafu with a gratuitous omission: <https://www.msn.com/en-us/news/technology/meta-found-a-new-way-to-violate-your-privacy-here-s-what-you-can-do/ar-AA1GecPs>
+ - ars comment about ublock origin setting: <https://arstechnica.com/security/2025/06/meta-and-yandex-are-de-anonymizing-android-users-web-browsing-identifiers/?comments=1&post=43767385>
+- spamprobe to spamassassin (notes in v3.txt)
+ - had to disable dnswl check, was causing grief
+ - `sa-check.py`, got 184/200 (~92% true positive rate)
+ - added `sa-train.sh`, runs nightly
+ - updated `~/.mailfilter`
+ - will monitor
+- cwe id in u16, cve id in u32
+ (`~/git/test/rust/nvd-cve/src/lib.rs`)
+- "quick numbers vs accurate numbers"
+ - quick disease test versus blood test
+ - BLS jobs reports
+- `polycvss` article about bit packing and `cvss-calcs`
## linkdump (2022-08-10):
- css bg fade:
<file:///data/home/pabs/git/test/html/css-bg-fade/index.html>
<https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload>
- https://www.mgaudet.ca/technical/2022/8/9/faster-ruby-thoughts-from-the-outside
-- https://www.fuzzingbook.org/
- https://security.googleblog.com/2022/05/retrofitting-temporal-memory-safety-on-c.html
- allocation in go: https://medium.com/eureka-engineering/understanding-allocations-in-go-stack-heap-memory-9a2631b5035d
(src: <https://old.reddit.com/r/golang/comments/wl7qyx/when_writing_functions_when_should_i_pass_by/iju1bhs/>)
@@ -581,8 +606,9 @@
- https://research.nccgroup.com/2022/08/16/wheel-of-fortune-outcome-prediction-taking-the-luck-out-of-gambling/
- https://carlineng.com/?postid=sql-critique#blog
- https://www.openssl.org/blog/blog/2022/08/24/FIPS-validation-certificate-issued/
-- constant-time fibonacci: https://specbranch.com/posts/const-fib/
-- https://fabiandablander.com/r/Fibonacci.html
+- constant-time fibonacci:
+ <https://specbranch.com/posts/const-fib/>
+ <https://fabiandablander.com/r/Fibonacci.html>
- https://specbranch.com/posts/common-perf-numbers/
- (reminds me of "tyranny of metrics"): <https://old.reddit.com/r/programming/comments/x37u7k/be_goodargumentdriven_not_datadriven/>
- chebyshev, taylor series: <https://specbranch.com/posts/faster-div8/>
@@ -648,6 +674,7 @@
<https://www.jwz.org/blog/2024/06/your-personal-information-is-very-important-to-us/>
- <https://arstechnica.com/gadgets/2024/08/nova-launcher-savior-of-cruft-filled-android-phones-is-on-life-support/>
- software: <https://www.lawfaremedia.org/article/the-crowdstrike-outage-and-market-driven-brittleness>
+- <https://github.com/C2SP/wycheproof>
## done
- add project folders
@@ -787,3 +814,16 @@
<http://pabstordmsrzhushs5drpb5mtb2ml56iyacidsjfebl2jlss65rlbsqd.onion/'>
(added to site backend)
- Projects: make each entry a `<li>`
+- set up logrotate for more granular `goaccess` reports. done, see
+ k3 notes and this gist:
+ <https://gist.github.com/pablotron/57aea9422a56bf59fedb3282bcc96109>
+- vanity `pablotron*.onion` address. done. url is:
+ <http://pablotronfils76sk6pwvyoosvfjbhxe3sn4c654e4na4szidbnbqdyd.onion/>
+- firefox tab groups (new in firefox 136). done: added to "firefox
+ redux" post
+- link to openvpn article in wayback machine:
+ <https://web.archive.org/web/20070812003116/http://www.linux-mag.com/id/2502>
+ (done: updated `content/posts/2006-03-19-openvpn*.html`)
+- openvpn article wayback link
+- site backend updates (nginx config)
+- armbian on odroid n2l
diff --git a/content/articles/site-backend.md b/content/articles/site-backend.md
index 5d5b199..e096e0d 100644
--- a/content/articles/site-backend.md
+++ b/content/articles/site-backend.md
@@ -544,7 +544,8 @@ The generated [HTML][] has been modified to:
## Onion Service
-This site is mirrored at the following [onion address][.onion]:
+This site is mirrored on the [Tor network][tor] at the following [onion
+address][.onion]:
[http://pablotronfils76sk6pwvyoosvfjbhxe3sn4c654e4na4szidbnbqdyd.onion/][pablotron.onion]
@@ -573,6 +574,35 @@ server {
# enable compression, compress common types
gzip on;
gzip_types text/html text/plain text/xml text/css text/javascript application/x-javascript text/csv application/json text/json image/svg+xml;
+
+ # security headers (see comments in apache config)
+ add_header "X-Frame-Options" "SAMEORIGIN";
+ add_header "X-Content-Type-Options" "nosniff";
+ add_header "Cross-Origin-Opener-Policy" "same-origin";
+ add_header "Cross-Origin-Resource-Policy" "same-origin";
+ add_header "Access-Control-Allow-Origin" "http://pablotronfils76sk6pwvyoosvfjbhxe3sn4c654e4na4szidbnbqdyd.onion";
+ add_header "Referrer-Policy" "strict-origin-when-cross-origin";
+ add_header "Permissions-Policy" "camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), usb=()";
+
+ # different from apache; POST method not needed
+ add_header "Access-Control-Allow-Methods" "GET, HEAD, OPTIONS";
+
+ location ~ \.(ico|jpg|jpeg|png|gif|webp|svg|js|json|css)$ {
+ # cache images, stylesheets, and javascript for 1 year
+ # note: caching makes a BIG difference when browsing via tor
+ expires 1y;
+ }
+
+ location ~ \.svg$ {
+ # relax Content-Security-Policy for SVGs to allow
+ # `style-src-attr 'unsafe-inline'`
+ add_header "Content-Security-Policy" "default-src 'self'; img-src 'self'; style-src-attr 'self' 'unsafe-inline'";
+ }
+
+ location ^~ \.svg$ {
+ # default Content-Security-Policy
+ add_header "Content-Security-Policy" "default-src 'self'; img-src 'self' https://pmdn.org";
+ }
}
```
@@ -654,6 +684,8 @@ published.
- 2025-04-26: Document [PNG][] [favicon][].
- 2025-05-12: Document [htmltest][] and [goaccess][].
- 2025-05-18: Add [Onion Service](#onion-service "Onion Service") section.
+- 2025-06-07: Add caching and security headers to [nginx][] config in
+ [Onion Service](#onion-service "Onion Service") section.
[s-hugo-configuration]: #hugo-configuration
"Hugo Configuration"
diff --git a/content/posts/2006-03-19-openvpn-article-in-linux-magazine.html b/content/posts/2006-03-19-openvpn-article-in-linux-magazine.html
index 319dd7e..18026de 100644
--- a/content/posts/2006-03-19-openvpn-article-in-linux-magazine.html
+++ b/content/posts/2006-03-19-openvpn-article-in-linux-magazine.html
@@ -5,8 +5,21 @@ title: OpenVPN Article in Linux Magazine
<p>
On the off-chance you haven't heard about it yet, I wrote an article
-on <a href='http://openvpn.net/'>OpenVPN</a> for <a href='http://www.linux-mag.com/'>Linux Magazine</a>.
+on <a href='https://openvpn.net/' title='OpenVPN'>OpenVPN</a> for <a
+ href='https://web.archive.org/http://www.linux-mag.com/'
+ title='Linux Magazine'
+>Linux Magazine</a>.
It's in the April 2006 issue, which has already been mailed to subscribers and should be available at
bookstores and on newsstands any day now.
</p>
+<p>
+<b>Update (2025-06-08):</b> Hello from 19 years later! The
+<a
+ href='https://web.archive.org/'
+ title='Wayback machine'
+>Wayback Machine</a> has an archived copy of the 2006 article: <a
+ href='https://web.archive.org/web/20070812003116/http://www.linux-mag.com/id/2502'
+ title='Casting Your Net with OpenVPN'
+>Casting Your Net with OpenVPN</a>.
+</p>
diff --git a/content/posts/2023-05-02-bookworm-and-podman.md b/content/posts/2023-05-02-bookworm-and-podman.md
index 63b842d..485f03a 100644
--- a/content/posts/2023-05-02-bookworm-and-podman.md
+++ b/content/posts/2023-05-02-bookworm-and-podman.md
@@ -9,7 +9,7 @@ a great release.
I've been looking for a suitable [Docker][] replacement for a few years
because of [their repeated license shenanigans][license-shenanigans].
-Last year I tried switching to [Podman][], but ran into into several
+Last year I tried switching to [Podman][], but ran into several
incompatibilities and minor annoyances.
[Podman 4.3][podman-4.3] ships with [Bookworm][] and seems to fix all
diff --git a/content/posts/2023-12-02-firefox-redux.md b/content/posts/2023-12-02-firefox-redux.md
index 28e51f9..75d78ef 100644
--- a/content/posts/2023-12-02-firefox-redux.md
+++ b/content/posts/2023-12-02-firefox-redux.md
@@ -21,10 +21,12 @@ Chrome to [Firefox][]. Thoughts so far...
### Firefox Cons
-- No tab groups. ~~There are several tab management extensions, but none
- are as elegant as tab groups.~~ (**Update:** [Tab Stash][] is a
- passable alternative for me).
-- Occasional [screen tearing][] on complex pages.
+- ~~No tab groups. There are several tab management extensions, but none
+ are as elegant as tab groups.~~ **Update:** Firefox 136 added tab
+ groups. I also like the [Tab Stash][] extension.
+- Occasional [screen tearing][] on complex pages. I think this is an
+ artifact of Firefox in [X11][], because it does not happen under
+ [Wayland][].
- Chrome has smoother scrolling.
I also worry about [Mozilla][] as an organization; a substantial portion
@@ -57,7 +59,10 @@ monopoly to an advertising company.
interface, supports [uBlock Origin][]. I've used it for years on my
phone and tablet.
-**Update (2023-12-04):** Added note about [Tab Stash][].
+Updates:
+- 2023-12-04: Added note about [Tab Stash][].
+- 2025-06-07: Added note about Tab Groups in Firefox 136 and clarify
+ that screen tearing only happens in [X11][].
[ublock origin]: https://en.wikipedia.org/wiki/UBlock_Origin
"Free and open source browser extension for content filtering and ad blocking."
@@ -104,5 +109,7 @@ monopoly to an advertising company.
"Portable Document Format (PDF)"
[tab stash]: https://addons.mozilla.org/en-US/firefox/addon/tab-stash/
"Tab Stash extension for Firefox"
-
-
+[x11]: https://en.wikipedia.org/wiki/X_Window_System
+ "X Window System"
+[wayland]: https://en.wikipedia.org/wiki/Wayland_(protocol)
+ "Wayland"
diff --git a/content/posts/2025-05-18-onion-service-mirror.md b/content/posts/2025-05-18-onion-service-mirror.md
index 053a76f..13bfca6 100644
--- a/content/posts/2025-05-18-onion-service-mirror.md
+++ b/content/posts/2025-05-18-onion-service-mirror.md
@@ -1,27 +1,25 @@
---
slug: onion-service-mirror
-title: "Onion Service Mirror"
+title: "Tor Site Mirror"
date: "2025-05-18T09:44:21-04:00"
---
-This site is now mirrored as an [onion service][] at the following
-([Tor][]-only) [URL][]:
+This site is now mirrored on the [Tor network][] at the following
+[onion address][]:
-[http://pabstordmsrzhushs5drpb5mtb2ml56iyacidsjfebl2jlss65rlbsqd.onion/][pabstor]
+[http://pablotronfils76sk6pwvyoosvfjbhxe3sn4c654e4na4szidbnbqdyd.onion/][pablotron.onion]
See [Site Backend - Onion Service][site-backend-onion-service] for more
details.
-[tor]: https://torproject.org/
+**Update (2025-06-02):** New [vanity .onion address][].
+
+[tor network]: https://torproject.org/
"The Onion Router"
-[onion service]: https://community.torproject.org/onion-services/
- "Service that can only be accessed via the Tor network."
-[pabstor]: http://pabstordmsrzhushs5drpb5mtb2ml56iyacidsjfebl2jlss65rlbsqd.onion
- "Onion service URL for this site."
+[pablotron.onion]: http://pablotronfils76sk6pwvyoosvfjbhxe3sn4c654e4na4szidbnbqdyd.onion/
+ "Site mirror onion address."
[site-backend-onion-service]: {{< relref "articles/site-backend" >}}#onion-service
"Site Backend, Onion Service"
-[url]: https://en.wikipedia.org/wiki/URL
- "Uniform resource locator (URL)"
-[.onion]: https://en.wikipedia.org/wiki/.onion
+[onion address]: https://en.wikipedia.org/wiki/.onion
"Top-level domain for onion services."
[mkp224o]: https://github.com/cathugger/mkp224o/
"Vanity .onion address generator"
diff --git a/content/posts/2025-06-07-uninstall-facebook.md b/content/posts/2025-06-07-uninstall-facebook.md
new file mode 100644
index 0000000..904d43b
--- /dev/null
+++ b/content/posts/2025-06-07-uninstall-facebook.md
@@ -0,0 +1,132 @@
+---
+slug: uninstall-facebook
+title: "Uninstall Facebook"
+date: "2025-06-07T18:08:27-04:00"
+---
+You should immediately remove the Facebook and Instagram apps from
+your Android devices:
+
+> We disclose a novel tracking method by Meta and Yandex potentially
+> affecting billions of Android users. We found that native Android
+> apps—including Facebook, Instagram, and several Yandex apps including
+> Maps and Browser—silently listen on fixed local ports for tracking
+> purposes.
+>
+> ...
+>
+> This web-to-app ID sharing method **bypasses typical privacy
+> protections such as clearing cookies, Incognito Mode and Android's
+> permission controls. Worse, it opens the door for potentially
+> malicious apps eavesdropping on users’ web activity.** (emphasis mine)
+
+[Source][local mess]
+
+[Ars Technica][] also has [an excellent summary][].
+
+In English: If you have the Facebook app or Instagram app installed on
+your Android device, then Meta may have secretly collected your identity
+and your browsing history.
+
+This is true even if you don't have a Facebook account. It's true even
+if you don't use the Facebook app. It's true even if you took steps to
+hide your browsing history like clearing cookies or using a private
+browser window.
+
+On June 3rd, Meta claimed that the code responsible had "been almost
+complete removed"; this is [weasel wording][] which actually means "the
+code has not been removed".
+
+Even if Meta actually did remove the code from their apps, there are
+still several problems:
+
+1. Meta has an [atrocious privacy record][]. It would be foolish to
+ take Meta at their word and they have a strong incentive to try
+ this again or something similar in the future.
+2. Removing code does not address the information Meta has already
+ collected. This information could be leaked in a data breach or
+ subpoenaed by law enforcement.
+3. Malicious or [trojaned][] apps could listen on the same local ports
+ and collect the same information. The [Local Mess][] researchers
+ demonstrated this with a proof-of-concept app.
+
+Additional privacy recommendations:
+
+1. Prefer web sites over apps. Many services use [deceptive patterns][]
+ to trick you into using an app instead of a web site. They do this
+ because an app can collect more information about you than a web site.
+2. Remove unused and rarely used apps.
+3. Stop using Google Search. I recommend [DuckDuckGo][].
+4. [Stop using Google Chrome][ditch-chrome]. I recommend [Firefox][]
+ with [uBlock Origin][] and some [configuration
+ changes][firefox-privacy]. Some folks swear by [DuckDuckGo Browser][],
+ but I haven't used it myself. See also: [The case for ditching
+ Chrome][vox-chrome]. If you really do need Chrome or Edge, then at
+ least install [uBlock Origin Lite][].
+5. Switch from Microsoft Windows to [Linux][]. I recommend [Ubuntu][]
+ for new users. I use [Debian][debian]. If you really do need
+ Windows, then at least [disable Windows telemetry][].
+6. Switch from text messaging and WhatsApp (owned by Meta) to [Signal][].
+7. Set up [Pi-hole][] on your home network. It has an easy-to-use web
+ interface and can help block ads and tracking on mobile devices and
+ "smart" TVs.
+8. Consider [Tor Browser][] or [Tails][] if the you need more protection
+ and are willing to accept some tradeoffs.
+
+Further reading: [Surveilance Self Defense][ssd]
+
+[local mess]: https://localmess.github.io/
+ "Local Mess: Tracking method used by Facebook, Instagram, and Yandex Android apps which bypasses privacy protection."
+[atrocious privacy record]: https://en.wikipedia.org/wiki/Privacy_concerns_with_Facebook
+ "Privacy concerns with Facebook (Wikipedia)"
+[ars technica]: https://arstechnica.com/security/2025/06/meta-and-yandex-are-de-anonymizing-android-users-web-browsing-identifiers/
+ "Ars Technica"
+[an excellent summary]: https://arstechnica.com/security/2025/06/meta-and-yandex-are-de-anonymizing-android-users-web-browsing-identifiers/
+ "Ars Technica: Meta and Yandex are de-anonymizing Android users’ web browsing identifiers"
+[weasel wording]: https://en.wikipedia.org/wiki/Weasel_word
+ "Weasel word: Word or phrase aimed at creating an impression that something specific and meaningful has been said, when in fact only a vague, ambiguous, or irrelevant claim has been communicated (Wikipedia)"
+[fingerprint]: https://www.amiunique.org/fingerprint
+ "fingerprint"
+[trojaned]: https://en.wikipedia.org/wiki/Trojan_horse_(computing)
+ "Trojan horse (Wikipedia)"
+[firefox]: https://www.mozilla.org/en-US/firefox/new/
+ "Mozilla Firefox web browser"
+[ublock origin]: https://en.wikipedia.org/wiki/UBlock_Origin
+ "uBlock Origin ad-blocker"
+[ditch-chrome]: {{< relref "posts/2023-12-02-firefox-redux.md" >}}#why-ditch-chrome
+ "Why Ditch Chrome?"
+[brave]: https://en.wikipedia.org/wiki/Brave_(web_browser)
+ "Brave web browser"
+[duckduckgo browser]: https://duckduckgo.com/app/
+ "DuckDuckGo web browser"
+[firefox-privacy]: https://cyberinsider.com/firefox-privacy/
+ "Firefox Privacy Checklist"
+[duckduckgo]: https://duckduckgo.com/
+ "DuckDuckGo search engine"
+[tor browser]: https://www.torproject.org/download/
+ "Tor Browser"
+[tor network]: https://www.torproject.org/
+ "Tor network"
+[linux]: https://en.wikipedia.org/wiki/Linux
+ "Linux operating system"
+[debian]: https://debian.org/
+ "Debian Linux"
+[ubuntu]: https://ubuntu.com/
+ "Ubuntu Linux"
+[disable windows telemetry]: https://windowsreport.com/disable-windows-11-telemetry/
+ "Disable Windows 11 telemetry"
+[pi-hole]: https://en.wikipedia.org/wiki/Pi-hole
+ "Pi-hole"
+[raspberry pi]: https://en.wikipedia.org/wiki/Raspberry_Pi
+ "Small single-board computer."
+[signal]: https://signal.org/
+ "Signal secure messenger"
+[ssd]: https://ssd.eff.org/
+ "Surveilance Self Defense"
+[tails]: https://tails.net/
+ "Tails: portable operating system that protects against surveillance and censorship"
+[vox-chrome]: https://www.vox.com/technology/387375/google-chrome-antitrust-privacy-android
+ "The case for ditching Chrome (vox.com)"
+[ublock origin lite]: https://en.wikipedia.org/wiki/UBlock_Origin#uBlock_Origin_Lite
+ "Manifest V3 version of uBlock Origin for Google Chrome, Microsoft Edge, and other Chromium-based browsers."
+[deceptive patterns]: https://www.deceptive.design/types
+ "Types of deceptive patterns"
diff --git a/content/posts/2025-06-08-armbian-on-odroid-n2l.md b/content/posts/2025-06-08-armbian-on-odroid-n2l.md
new file mode 100644
index 0000000..3443adf
--- /dev/null
+++ b/content/posts/2025-06-08-armbian-on-odroid-n2l.md
@@ -0,0 +1,145 @@
+---
+slug: armbian-on-odroid-n2l
+title: "Armbian on Odroid N2L"
+date: "2025-06-08T15:31:00-04:00"
+
+pics:
+ n2l:
+ css: "image"
+ tip: "Odroid N2L running Armbian."
+ sources:
+ - "/files/posts/armbian-on-odroid-n2l/n2l-1024.webp"
+ - src: "/files/posts/armbian-on-odroid-n2l/n2l-1024.png"
+ width: 1024
+ height: 771
+---
+
+Last week I installed [Armbian][] on an [Odroid N2L][]. The
+installation steps, installation results, and fixes for some problems
+are documented below.
+
+### Installation
+
+1. Download and import the [signing key][armbian-key] (fingerprint
+ `DF00FAF1C577104B50BF1D0093D6889F9F0E78D5`): \
+ `wget -O- https://apt.armbian.com/armbian.key | gpg -- import -`
+2. Download the current "Debian 12 (Bookworm)" image and the [detached
+ signature][asc] from the "Minimal/IOT images" section of the [Armbian
+ Odroid N2L page][armbian-n2l].
+3. Verify the [signature][asc]: \
+ `gpg --verify Armbian_community_25.8.0-trunk.8_Odroidn2l_bookworm_current_6.12.28_minimal.img.xz{.asc,}`
+4. Uncompress the image: \
+ `unxz Armbian_community_25.8.0-trunk.8_Odroidn2l_bookworm_current_6.12.28_minimal.img.xz`
+5. Flash the uncompressed image to a [microSD][] card: \
+ `sudo dd if=Armbian_community_25.8.0-trunk.8_Odroidn2l_bookworm_current_6.12.28_minimal.img of=/dev/sda bs=1M status=progress`
+6. Mount the second partition of the [microSD][] card on `/mnt/tmp`: \
+ `sudo mount /dev/sda2 /mnt/tmp`
+7. Use the instructions and template from [Automatic first boot
+ configuration][armbian-autoconfig] to populate
+ `/mnt/tmp/root/.not_logged_in_yet`. My populated autoconfig is
+ [here][populated-autoconfig], but **it did not work as expected**;
+ see below.
+8. Unmount the second partition of the [microSD][] card.
+9. Insert the [microSD][] card into the [Odroid N2L][] and power it on.
+
+### Installation Results
+
+Worked as expected:
+
+- Successfully booted.
+- Successfully connected to [WiFi][] on first boot.
+
+Did not work as expected:
+
+- Did not connect to WiFI on subsequent boots.
+- Did not set the root password. Instead the root password was `1234`.
+- Did not set the user password.
+- Did not set the user SSH key.
+
+### Fixes
+
+To correct these problems I connected a keyboard and monitor and did the
+following:
+
+1. Logged in as `root` with the password `1234`.
+2. Changed the root password and the user password.
+4. Edited `/etc/netplan/20-eth-fixed-mac.yaml` and fixed the
+ errors. The corrected version is below.
+5. Ran `netplan apply` to apply the corrected network configuration.
+6. Rebooted to confirm that networking was working as expected.
+
+Here is the corrected `/etc/netplan/20-eth-fixed-mac.yaml`:
+
+```yaml
+network:
+ version: 2
+```
+&nbsp;
+
+After fixing networking, I did the following:
+
+1. Copied my SSH key.
+2. Edited `/etc/ssh/sshd_config` to disable root logins and password
+ logins.
+3. Ran `apt-get update && apt-get upgrade`.
+4. Installed `unattended-upgrades`.
+5. Rebooted to pick up the latest updates.
+
+<!--
+
+### Conclusion
+
+Many non-[Pi][] [SBCs][sbc] manufacturers stop providing software
+shortly after the hardware is released. Owners are stuck with
+unsupported hardware running out-of-date software.
+
+Case in point: The latest download on the [Odroid N2L wiki][] is Ubuntu
+22.04.
+
+I'm thrilled that [Armbian][]
+
+original unused blather ...
+
+[Armbian][] now supports the [Odroid N2L][] as a [community maintained
+target][armbian-n2l].
+
+Context: A couple of years ago Nadine bought me a pair of [Odroid
+N2Ls][odroid n2l]. [Pi 4s][pi] were scarce because of supply chain
+issues, and the [Odroid N2L][] seemed like a decent substitute.
+
+The problem with non-[Pi][] [SBCs][sbc] is that the manufacturers
+invariably stop providing software updates shortly after release, so you
+are stuck with unsupported hardware running an out of date OS.
+
+As of this writing, the [Odroid N2L wiki][] still has the same software
+that it did when first got the hardware: Ubuntu 22.04.
+-->
+
+[{{< pe-figure "n2l" >}}][n2l-pic]
+
+[armbian]: https://www.armbian.com/
+ "Linux for ARM development boards"
+[odroid n2l]: https://www.hardkernel.com/shop/odroid-n2l-with-4gbyte-ram/
+ "Odroid N2L ARM A73 SBC"
+[pi]: https://en.wikipedia.org/wiki/Raspberry_Pi
+ "Raspberry Pi"
+[sbc]: https://en.wikipedia.org/wiki/Single-board_computer
+ "single-board computer (SBC)"
+[armbian-n2l]: https://www.armbian.com/odroid-n2l/
+ "Armbian for the Odroid N2L"
+[odroid n2l wiki]: https://wiki.odroid.com/getting_started/os_installation_guide#tab__odroid-n2l
+ "Odroid Wiki: Odroid N2L"
+[n2l-pic]: /files/posts/armbian-on-odroid-n2l/n2l.jpg
+ "Odroid N2L running Armbian"
+[armbian-autoconfig]: https://docs.armbian.com/User-Guide_Autoconfig/
+ "Armbian Documentation: Automatic first boot configuration"
+[asc]: https://en.wikipedia.org/wiki/Pretty_Good_Privacy#Digital_signatures
+ "Detached PGP signature"
+[armbian-key]: https://apt.armbian.com/armbian.key
+ "Armbian PGP signing key"
+[populated-autoconfig]: /files/posts/armbian-on-odroid-n2l/odroid-n2l-root_not_logged_in_yet.txt
+ "Populated automatic first boot configuration file"
+[microsd]: https://en.wikipedia.org/wiki/SD_card#microSD
+ "microSD memory card"
+[wifi]: https://en.wikipedia.org/wiki/Wi-Fi
+ "Wireless networking"
diff --git a/content/posts/2025-06-08-nginx-caching-and-security-headers.md b/content/posts/2025-06-08-nginx-caching-and-security-headers.md
new file mode 100644
index 0000000..54cd4a0
--- /dev/null
+++ b/content/posts/2025-06-08-nginx-caching-and-security-headers.md
@@ -0,0 +1,27 @@
+---
+slug: nginx-caching-and-security-headers
+title: "Nginx Caching and Security Headers"
+date: "2025-06-08T13:16:00-04:00"
+---
+
+Yesterday I ported the [caching and security headers][apache-config]
+from the [Apache][] configuration for the public site to the [Nginx][]
+configuration for the [Tor mirror][].
+
+The caching headers are particularly helpful for the [Tor mirror][].
+
+The updated [Nginx][] configuration and additional documentation are
+here: [Site Backend - Onion Service][onion-service].
+
+[apache-config]: {{< relref "articles/site-backend" >}}#apache-configuration
+ "Site Backend - Apache Configuration"
+[apache]: https://apache.org/
+ "Apache web server"
+[nginx]: https://nginx.org/
+ "Nginx web server"
+[onion-service]: {{< relref "articles/site-backend" >}}#onion-service
+ "Site Backend - Onion Service"
+[tor mirror]: {{< relref "posts/2025-05-18-onion-service-mirror" >}}
+ "Tor Site Mirror"
+[tor network]: https://torproject.org/
+ "Tor project"
diff --git a/content/posts/2025-06-08-old-openvpn-article.md b/content/posts/2025-06-08-old-openvpn-article.md
new file mode 100644
index 0000000..67f2ccf
--- /dev/null
+++ b/content/posts/2025-06-08-old-openvpn-article.md
@@ -0,0 +1,36 @@
+---
+slug: old-openvpn-article
+title: "Old OpenVPN Article"
+date: "2025-06-08T11:52:22-04:00"
+---
+
+In 2006 [I wrote an article about OpenVPN][article-post] for the
+now-defunct [Linux Magazine][]. This week I found a copy of the 2006
+article on the [Wayback Machine][]:
+
+[Casting Your Net with OpenVPN (Wayback Machine)][article]
+
+In 2025 you should prefer [Wireguard][] over [OpenVPN][] because
+[Wireguard][] is [faster, more secure, and easier to use][wg-reasons].
+
+Fun factoid: The [AWS Client VPN][] is just an [AWS][]-branded build of
+the [OpenVPN][] client.
+
+[article-post]: {{< relref "posts/2006-03-19-openvpn-article-in-linux-magazine" >}}
+ "OpenVPN Article in Linux Magazine"
+[linux magazine]: https://web.archive.org/http://www.linux-mag.com/
+ "Linux Magazine"
+[wayback machine]: https://web.archive.org/
+ "Wayback Machine"
+[article]: https://web.archive.org/web/20070812003116/http://www.linux-mag.com/id/2502'
+ "Casting Your Net with OpenVPN (Wayback Machine)"
+[aws]: https://aws.amazon.com/
+ "Amazon Web Services (AWS)"
+[aws client vpn]: https://aws.amazon.com/vpn/client-vpn-download/
+ "AWS Client VPN"
+[openvpn]: https://openvpn.net/
+ "OpenVPN"
+[wg-reasons]: {{< relref "posts/2021-11-06-wireguard-is-awesome" >}}
+ "Wireguard is Awesome"
+[wireguard]: https://wireguard.com/
+ "Wireguard"
diff --git a/content/posts/2025-10-04-polycvss-v0.2.0.md b/content/posts/2025-10-04-polycvss-v0.2.0.md
new file mode 100644
index 0000000..49d20f7
--- /dev/null
+++ b/content/posts/2025-10-04-polycvss-v0.2.0.md
@@ -0,0 +1,143 @@
+---
+slug: polycvss-v0.2.0
+title: "polycvss v0.2.0"
+date: "2025-10-04T03:15:48-04:00"
+---
+I just released [polycvss][] version 0.2.0.
+
+[polycvss][] is a [Rust][] library to parse and score [CVSS][] vector
+strings.
+
+Features:
+
+- [CVSS v2][doc-v2], [CVSS v3][doc-v3], and [CVSS v4][doc-v4] support.
+- Version-agnostic parsing and scoring [API][].
+- Memory efficient: Vectors are 8 bytes. Scores and severities are 1 byte.
+- No dependencies by default except the standard library.
+- Optional [serde][] integration via the `serde` build feature.
+- Extensive tests: Tested against thousands of vectors and scores from
+ the [NVD][] [CVSS][] calculators.
+
+Here is an example tool which parses the first command-line argument as
+a [CVSS][] vector string, then prints the score and severity:
+
+```rust
+use polycvss::{Err, Score, Severity, Vector};
+
+fn main() -> Result<(), Err> {
+ let args: Vec<String> = std::env::args().collect(); // get cli args
+
+ if args.len() == 2 {
+ let vec: Vector = args[1].parse()?; // parse string
+ let score = Score::from(vec); // get score
+ let severity = Severity::from(score); // get severity
+ println!("{score} {severity}"); // print score and severity
+ } else {
+ let name = args.first().map_or("app", |s| s); // get app name
+ eprintln!("Usage: {name} [VECTOR]"); // print usage
+ }
+
+ Ok(())
+}
+```
+&nbsp;
+
+Here is the example tool output for a [CVSS v2][doc-v2] vector string, a
+[CVSS v3][doc-v3] vector string, and a [CVSS v4][doc-v4] vector string:
+
+```sh
+# test with cvss v2 vector string
+$ cvss-score "AV:A/AC:H/Au:N/C:C/I:C/A:C"
+6.8 MEDIUM
+
+# test with cvss v3 vector string
+$ cvss-score "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
+9.8 CRITICAL
+
+# test with cvss v4 vector string
+$ cvss-score "CVSS:4.0/AV:L/AC:H/AT:N/PR:N/UI:P/VC:L/VI:L/VA:L/SC:H/SI:H/SA:H"
+5.2 MEDIUM
+```
+&nbsp;
+
+This example tool is included in the [Git repository][] as
+[`src/bin/cvss-score.rs`][cvss-score].
+
+### Links
+
+- [polycvss Git repository][polycvss]
+- [polycvss package on crates.io][crates-io-polycvss]
+- [polycvss API Documentation on docs.rs][docs-rs-polycvss]
+
+**Updates**
+
+- 2025-10-12: [polycvss v0.2.1][]: Add [`polycvss::v4::Nomenclature`][v4-nomenclature] and improve documentation.
+- 2025-10-18: [polycvss v0.3.0][]: Add user-friendly `Error` messages, remove unreleased CVSS v2.x `Version` variants, and improve documentation.
+- 2025-10-19: [polycvss v0.3.1][]: Documentation improvements.
+- 2025-11-16: [polycvss v0.3.2][]: Add `impl From<Vector> for Severity`
+ and `examples/` directory.
+
+[html]: https://en.wikipedia.org/wiki/HTML
+ "HyperText Markup Language"
+[rust]: https://rust-lang.org/
+ "Rust programming language."
+[cvss]: https://www.first.org/cvss/
+ "Common Vulnerability Scoring System (CVSS)"
+[doc-v2]: https://www.first.org/cvss/v2/guide
+ "CVSS v2.0 Documentation"
+[doc-v3]: https://www.first.org/cvss/v3-1/specification-document
+ "CVSS v3.1 Specification"
+[doc-v4]: https://www.first.org/cvss/v4-0/specification-document
+ "Common Vulnerability Scoring System (CVSS) version 4.0 Specification"
+[bit-field]: https://en.wikipedia.org/wiki/Bit_field
+ "Bit field (Wikipedia)"
+[cvss-score]: https://github.com/pablotron/polycvss/blob/main/src/bin/cvss-score.rs
+ "Example command-line tool which parses a CVSS vector and prints the score and severity to standard output."
+[git repository]: https://github.com/pablotron/polycvss
+ "polycvss git repository"
+[polycvss]: https://github.com/pablotron/polycvss
+ "polycvss Rust library"
+[v2-calc]: https://nvd.nist.gov/vuln-metrics/cvss/v2-calculator
+ "NVD CVSS v2 calculator"
+[v3-calc]: https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator
+ "NVD CVSS v3 calculator"
+[v4-calc]: https://nvd.nist.gov/site-scripts/cvss-v4-calculator-main/
+ "NVD CVSS v4 calculator"
+[cargo]: https://doc.rust-lang.org/cargo/
+ "Rust package manager"
+[podman]: https://podman.io/
+ "Podman container management tool"
+[docker]: https://docker.com/
+ "Docker container management tool"
+[api]: https://en.wikipedia.org/wiki/API
+ "Application Programming Interface (API)"
+[linter]: https://en.wikipedia.org/wiki/Lint_(software)
+ "Static code analysis tool to catch common mistakes"
+[src-v2-rs]: src/v2.rs
+ "CVSS v2 parsing and scoring"
+[src-v3-rs]: src/v3.rs
+ "CVSS v3 parsing and scoring"
+[src-v4-rs]: src/v4.rs
+ "CVSS v4 parsing and scoring"
+[nvd]: https://nvd.nist.gov/
+ "National Vulnerability Database (NVD)"
+[cvss-calcs]: https://github.com/pablotron/cvss-calcs
+ "Generate random CVSS vector strings and score them."
+[crates.io]: https://crates.io/
+ "Rust package registry"
+[docs-rs-polycvss]: https://docs.rs/polycvss
+ "polycvss API documentation on docs.rs"
+[crates-io-polycvss]: https://crates.io/crates/polycvss
+ "polycvss on crates.io"
+[serde]: https://serde.rs/
+ "Rust serializing and deserializing framework."
+[polycvss v0.2.1]: https://github.com/pablotron/polycvss/releases/tag/0.2.1
+ "polycvss version 0.2.1"
+[polycvss v0.3.0]: https://github.com/pablotron/polycvss/releases/tag/0.3.0
+ "polycvss version 0.3.0"
+[polycvss v0.3.1]: https://github.com/pablotron/polycvss/releases/tag/0.3.1
+ "polycvss version 0.3.1"
+[polycvss v0.3.2]: https://github.com/pablotron/polycvss/releases/tag/0.3.2
+ "polycvss version 0.3.2"
+[v4-nomenclature]: https://docs.rs/polycvss/latest/polycvss/v4/enum.Nomenclature.html
+ "polycvss::v4::Nomenclature documentation."
diff --git a/content/projects/polycvss.md b/content/projects/polycvss.md
new file mode 100644
index 0000000..eddea7a
--- /dev/null
+++ b/content/projects/polycvss.md
@@ -0,0 +1,10 @@
+---
+title: "polycvss"
+slug: "polycvss"
+active: true
+repo: "https://github.com/pablotron/polycvss"
+text: "Self-contained C11 SHA-3 implementation."
+text: "Rust library for CVSS vector string parsing and score calculation."
+text: "Rust library to parse and score CVSS vector strings."
+---
+Rust library to parse and score CVSS vector strings.
diff --git a/data/projects.yaml b/data/projects.yaml
index 60e8a48..f800edd 100644
--- a/data/projects.yaml
+++ b/data/projects.yaml
@@ -16,6 +16,11 @@
repo: "https://github.com/pablotron/luigi-template"
text: "String templating library for Java, JavaScript, PHP, and Ruby."
+- name: "polycvss"
+ slug: "polycvss"
+ repo: "https://github.com/pablotron/polycvss"
+ text: "Rust library to parse and score CVSS vector strings."
+
- name: "SHA2"
slug: "sha2"
repo: "https://github.com/pablotron/sha2"
diff --git a/static/files/articles/site-backend/pablotron.onion.conf.txt b/static/files/articles/site-backend/pablotron.onion.conf.txt
index 26b340b..9c80ede 100644
--- a/static/files/articles/site-backend/pablotron.onion.conf.txt
+++ b/static/files/articles/site-backend/pablotron.onion.conf.txt
@@ -8,4 +8,33 @@ server {
# enable compression, compress common types
gzip on;
gzip_types text/html text/plain text/xml text/css text/javascript application/x-javascript text/csv application/json text/json image/svg+xml;
+
+ # security headers (see comments in apache config)
+ add_header "X-Frame-Options" "SAMEORIGIN";
+ add_header "X-Content-Type-Options" "nosniff";
+ add_header "Cross-Origin-Opener-Policy" "same-origin";
+ add_header "Cross-Origin-Resource-Policy" "same-origin";
+ add_header "Access-Control-Allow-Origin" "http://pablotronfils76sk6pwvyoosvfjbhxe3sn4c654e4na4szidbnbqdyd.onion";
+ add_header "Referrer-Policy" "strict-origin-when-cross-origin";
+ add_header "Permissions-Policy" "camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), usb=()";
+
+ # different from apache; POST method not needed
+ add_header "Access-Control-Allow-Methods" "GET, HEAD, OPTIONS";
+
+ location ~ \.(ico|jpg|jpeg|png|gif|webp|svg|js|json|css)$ {
+ # cache images, stylesheets, and javascript for 1 year
+ # note: caching makes a BIG difference when browsing via tor
+ expires 1y;
+ }
+
+ location ~ \.svg$ {
+ # relax Content-Security-Policy for SVGs to allow
+ # `style-src-attr 'unsafe-inline'`
+ add_header "Content-Security-Policy" "default-src 'self'; img-src 'self'; style-src-attr 'self' 'unsafe-inline'";
+ }
+
+ location ^~ \.svg$ {
+ # default Content-Security-Policy
+ add_header "Content-Security-Policy" "default-src 'self'; img-src 'self' https://pmdn.org";
+ }
}
diff --git a/static/files/pabs.asc b/static/files/pabs.asc
index 9bda0d2..555912f 100644
--- a/static/files/pabs.asc
+++ b/static/files/pabs.asc
@@ -2,27 +2,27 @@
mDMEZPpC4BYJKwYBBAHaRw8BAQdAozyRcx2w+Eb6m6VBVEp3EnfdOsH1SGgY7Bf0
7F7zP2C0H1BhdWwgRHVuY2FuIDxncGdAcGFibG90cm9uLm9yZz6ImQQTFggAQQIb
-AQUJA+MNIAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgBYhBAIRNlIVSOsZj2T/c44Y
-JTTN0fK4BQJk+kTGAhkBAAoJEI4YJTTN0fK4bnMA/RAZ5S31GTIrZUA3JmZvCvwq
-k3rtWxL6BDhco8yQOdQuAQCM6qSHN4rXr+6ztIe3EvkpWU8lXh1Uc3Krki5kTzQA
-ArQrUGF1bCBEdW5jYW4gKGdpdGh1YikgPGdpdGh1YkBwYWJsb3Ryb24ub3JnPoiW
-BBMWCAA+FiEEAhE2UhVI6xmPZP9zjhglNM3R8rgFAmT6RJ4CGwEFCQPjDSAFCwkI
-BwIGFQoJCAsCBBYCAwECHgECF4AACgkQjhglNM3R8rjyvwD+PbyFukeFU6SMTGa0
-5ciR5WbhXhRHm19f0i+i8dfjRGQA/ifcNa6L+jefQUY5r2eIcjo+5AyANKeQQX1E
-atOoS14HtCtQYXVsIER1bmNhbiAocGVyc29uYWwpIDxwYWJzQHBhYmxvdHJvbi5v
-cmc+iJYEExYIAD4WIQQCETZSFUjrGY9k/3OOGCU0zdHyuAUCZPpEvAIbAQUJA+MN
-IAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRCOGCU0zdHyuPdVAQCktsGno4Rs
-2F+mpkBL/XAZygGcXTex87GBk+9UHTIFoAD/W2IxS3sXhG84+dVuXawEjbVAsZnY
-JXgo/Yp89t3FcQO4MwRk+kMGFgkrBgEEAdpHDwEBB0CXyafK+3r6c+foOGSypcN3
-DDpRJ4E08hZrLlMDo66tmYj1BBgWCAAmFiEEAhE2UhVI6xmPZP9zjhglNM3R8rgF
-AmT6QwYCGwIFCQPjDPoAgQkQjhglNM3R8rh2IAQZFggAHRYhBMxaPAkB8qSbHzks
-9w9m3LNb0xXvBQJk+kMGAAoJEA9m3LNb0xXvnlsA/2XAWLXyMSTTGBVLN3V96gpT
-L/jm2fincNSBkk5heOT3AP0SM6I8I7yBN8a9HyRW7of7dISp1DPRej7zjba+w2DW
-D02/AQDOFVyNA8nFU8VIply2q0f5cWremdEyKZsMQOoV7h8YrwEAkZPruamwJOhb
-dERvNLzLRfTy4Ur21AZQCbNDO1PiEgi4OARk+kMWEgorBgEEAZdVAQUBAQdAnLxb
-gFTx1NB4SrLsKOV/3zZkwGiPHhwNy1rf8czSlCUDAQgHiH4EGBYIACYWIQQCETZS
-FUjrGY9k/3OOGCU0zdHyuAUCZPpDFgIbDAUJA+MM6gAKCRCOGCU0zdHyuH71AQCL
-EetpJgsLGwm0qqwPMIwk38h/VfsG5B4cSOiP5KFfKQD+Ko6KWtGkgwS2k8IgqEng
-GdWY8q5PwXp8FHsdOC7QuQI=
-=84QG
+AQULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAIZARYhBAIRNlIVSOsZj2T/c44YJTTN
+0fK4BQJozgCMBQkHliSsAAoJEI4YJTTN0fK4fNkBAN0ytDOHZbjWJIuGRp/VvtAn
+EIz5ngsqEr60uMvv5t7eAQC0AgQ2o2J/AHwou7V0fz2uISH9QSHMGw/Y5Hjn6RX+
+BbQrUGF1bCBEdW5jYW4gKGdpdGh1YikgPGdpdGh1YkBwYWJsb3Ryb24ub3JnPoiW
+BBMWCAA+AhsBBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAFiEEAhE2UhVI6xmPZP9z
+jhglNM3R8rgFAmjOAIwFCQeWJKwACgkQjhglNM3R8rilewEA19Lc/7iWIkmIWSTI
+veXUZD0dCNzOg0nhhl7GEMoK/foA/24+KVQUWU2AJka4RNb4glVqo1b6UNq2IOZr
+rLmZv5sLtCtQYXVsIER1bmNhbiAocGVyc29uYWwpIDxwYWJzQHBhYmxvdHJvbi5v
+cmc+iJYEExYIAD4CGwEFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AWIQQCETZSFUjr
+GY9k/3OOGCU0zdHyuAUCaM4AjAUJB5YkrAAKCRCOGCU0zdHyuLUSAQDSQS2OQa/E
+VdAyRd1LR8jR7WPaHAyXbPanOC8x+3AksQEAx3gwp0ZBxAhj7lwlzuqAdxWy1Eiu
++9O1gAcEyDzULgS4MwRk+kMGFgkrBgEEAdpHDwEBB0CXyafK+3r6c+foOGSypcN3
+DDpRJ4E08hZrLlMDo66tmYj1BBgWCAAmAhsCFiEEAhE2UhVI6xmPZP9zjhglNM3R
+8rgFAmjOATAFCQeWJSoAgXYgBBkWCAAdFiEEzFo8CQHypJsfOSz3D2bcs1vTFe8F
+AmT6QwYACgkQD2bcs1vTFe+eWwD/ZcBYtfIxJNMYFUs3dX3qClMv+ObZ+Kdw1IGS
+TmF45PcA/RIzojwjvIE3xr0fJFbuh/t0hKnUM9F6PvONtr7DYNYPCRCOGCU0zdHy
+uGg/AP9Vj/sL5GoNcvgx8d7SdKV+GWAmJnGFAszAkPsA4vCULgD/cSP+mafM9Xdf
+mCEYA2Wcps/nPOkJoXJDfFcyO0vMVwO4OARk+kMWEgorBgEEAZdVAQUBAQdAnLxb
+gFTx1NB4SrLsKOV/3zZkwGiPHhwNy1rf8czSlCUDAQgHiH4EGBYIACYCGwwWIQQC
+ETZSFUjrGY9k/3OOGCU0zdHyuAUCaM4BEwUJB5Yk/QAKCRCOGCU0zdHyuOehAP0W
+QeLan4L834js6/UJ3Cow8T+QLEaJxCKGrEhYOwjrQQD8CU/3XuO6FKRFIZsC57Lw
+uWmtrMiaRtxcEjoL7GEsOw0=
+=qJVW
-----END PGP PUBLIC KEY BLOCK-----
diff --git a/static/files/posts/armbian-on-odroid-n2l/n2l-1024.png b/static/files/posts/armbian-on-odroid-n2l/n2l-1024.png
new file mode 100644
index 0000000..4809ded
--- /dev/null
+++ b/static/files/posts/armbian-on-odroid-n2l/n2l-1024.png
Binary files differ
diff --git a/static/files/posts/armbian-on-odroid-n2l/n2l-1024.webp b/static/files/posts/armbian-on-odroid-n2l/n2l-1024.webp
new file mode 100644
index 0000000..4a91338
--- /dev/null
+++ b/static/files/posts/armbian-on-odroid-n2l/n2l-1024.webp
Binary files differ
diff --git a/static/files/posts/armbian-on-odroid-n2l/n2l.jpg b/static/files/posts/armbian-on-odroid-n2l/n2l.jpg
new file mode 100644
index 0000000..8553d86
--- /dev/null
+++ b/static/files/posts/armbian-on-odroid-n2l/n2l.jpg
Binary files differ
diff --git a/static/files/posts/armbian-on-odroid-n2l/odroid-n2l-root_not_logged_in_yet.txt b/static/files/posts/armbian-on-odroid-n2l/odroid-n2l-root_not_logged_in_yet.txt
new file mode 100644
index 0000000..2f03dae
--- /dev/null
+++ b/static/files/posts/armbian-on-odroid-n2l/odroid-n2l-root_not_logged_in_yet.txt
@@ -0,0 +1,44 @@
+#
+# armbian automatic first boot configuration based on the documentation
+# at https://docs.armbian.com/User-Guide_Autoconfig/
+#
+# NOTE: This configuration did NOT work as expected.
+#
+# In particular, it had the following errors:
+#
+# - did not set the root password. instead the root password was "1234"
+# - did not set the user password
+# - generated a broken network configuration which did not work after
+# the second boot
+#
+
+# Network Settings
+PRESET_NET_CHANGE_DEFAULTS="1"
+
+## Ethernet
+PRESET_NET_ETHERNET_ENABLED="1" # Ignored due to WiFi
+
+## WiFi
+PRESET_NET_WIFI_ENABLED="1"
+PRESET_NET_WIFI_SSID="MY WIFI SSID"
+PRESET_NET_WIFI_KEY="MY WIFI PASSWORD"
+PRESET_NET_WIFI_COUNTRYCODE="US"
+PRESET_CONNECT_WIRELESS="y"
+## Static IP
+PRESET_NET_USE_STATIC="0"
+
+# System
+SET_LANG_BASED_ON_LOCATION="y"
+PRESET_LOCALE="en_US.UTF-8"
+PRESET_TIMEZONE="US/Eastern"
+
+# Root
+PRESET_ROOT_PASSWORD="MY ROOT PASSWORD"
+PRESET_ROOT_KEY=""
+
+# User
+PRESET_USER_NAME="someuser"
+PRESET_USER_PASSWORD="MY USER PASSWORD"
+PRESET_USER_KEY="URL TO SSH KEY"
+PRESET_DEFAULT_REALNAME="Some User"
+PRESET_USER_SHELL="bash"