Bound by paws, guided by spirit.

Creating destiny through every high and low. Running on BSD, powered by four paws and an endless rabbit hole of coffee and code.
10 // 2026-04-14

🐡 // Spot on: The status of the system (7 day´s later Director´s Cut)

# uptime 12:16AM up 7 days, 4:28, 1 user, load averages: 0.22, 0.21, 0.21 # pfctl -s info Status: Enabled for 7 days 04:29:33 Debug: err Interface Stats for egress IPv4 IPv6 Bytes In 477307976 92274679 Bytes Out 744422222 156357351 Packets In Passed 4147071 870447 Blocked 187684 27027 Packets Out Passed 3421016 432098 Blocked 30 17 State Table Total Rate current entries 257 half-open tcp 0 searches 9057159 14.6/s inserts 707946 1.1/s removals 707689 1.1/s Counters match 957851 1.5/s bad-offset 0 0.0/s fragment 0 0.0/s short 28225 0.0/s normalize 0 0.0/s memory 0 0.0/s bad-timestamp 0 0.0/s congestion 0 0.0/s ip-option 6 0.0/s proto-cksum 15 0.0/s state-mismatch 50 0.0/s state-insert 0 0.0/s state-limit 0 0.0/s src-limit 70 0.0/s synproxy 0 0.0/s translate 0 0.0/s no-route 0 0.0/s
uptime, pfctl -s info
# doveconf imap_idle_notify_interval imap_idle_notify_interval = 2 mins # zgrep -a 'IDLE running for' /var/log/maillog.{0,1,2,3,4,5,6}.gz /var/log/maillog /var/log/maillog.0.gz:Apr 13 09:11:30 mail dovecot: imap(user)<46527><2 ... N>: Disconnected: Connection closed (IDLE running for 0.001 + waiting input for 626.187 secs ... # Waiting input is the client side, IDLE the dovecot server. Maybe you remember the rate limits of pf.
Status of the ChatMail server.
cat /var/log/rspamd/rspamd.log | wc -l 10637
/var/log/rspamd/rspamd.log
zgrep -a 'GREY' /var/log/daemon.{0,1}.gz /var/log/daemon | wc -l 51
Greylisting of Spamd.
# top -b load averages: 0.38, 0.26, 0.22 mail.floof.sbs 00:24:58 78 processes: 1 running, 76 idle, 1 on processor up 7 days 04:35:58 CPU states: 1.3% user, 0.0% nice, 0.4% sys, 0.0% spin, 0.9% intr, 97.4% idle Memory: Real: 283M/1305M act/tot Free: 648M Cache: 390M Swap: 0K/2288M PID P N SIZE RES STATE WAIT TIME CPU COMMAND 10974 2 0 1864K 4356K sleep kqread 2:40 0.05% relayd 72110 10 0 74M 41M idle fsleep 5:17 0.00% nostr-r. 79905 2 0 1108K 2836K idle kqread 4:25 0.00% sshd 92607 2 0 1860K 4340K idle kqread 2:51 0.00% relayd 41908 2 0 1856K 4332K sleep kqread 2:46 0.00% relayd 9382 2 0 17M 4628K sleep kqread 1:32 0.00% redis-s. 25578 2 0 59M 30M sleep kqread 1:09 0.00% rspamd 43256 2 0 3840K 6820K sleep kqread 0:47 0.00% relayd 66780 2 0 3700K 6672K sleep kqread 0:45 0.00% relayd 80498 2 0 4044K 7020K sleep kqread 0:44 0.00% relayd 47026 4 0 988K 1504K sleep bpf 0:43 0.00% spamlogd 27311 2 0 61M 37M sleep kqread 0:41 0.00% rspamd 77740 2 0 33M 33M sleep kqread 0:38 0.00% nsd 11840 2 0 6196K 5872K sleep kqread 0:34 0.00% keyboxd 23696 10 0 10M 1636K idle nanoslp 0:28 0.00% spamd 33378 2 0 2756K 4692K sleep kqread 0:16 0.00% httpd 24049 2 0 3184K 5180K sleep kqread 0:15 0.00% httpd 48446 2 0 2728K 4648K sleep kqread 0:15 0.00% httpd # Without Usernames as line-breaks makes the output # unreadable, P is Pri., N is Nice.
top -b

Efficiency is not an option, it´s a philosophy. 283MB active memory for a full sovereign stack.

Sources:

Wikipedia: just imagine, they have a search box, use it, it is free
09 // 2026-04-12

🧬 // Steganographic multi-layered bio-cipher (Biopunk meets Geopunk Director´s Cut)

Up to new horizons.

You remeber biology/genetics in shool, probably not but that´s ok.

  • Antiparallel Strings: DNA is a double helix where the two strands 5´ -> 3´ and 3´ -> 5´ are complementary mirrors (running in opposite directions where A pairs with T, C pairs with G). A message on the coding strand looks like noise on the template strand.
  • The Compiler (Transcription/Splicing): The cell doesn´t execute the whole strand. It transcribes DNA into mRNA based on segments with a given start and stop primer and then performs splicing.
  • Exons vs. Introns: A gene consists of exons (the actual „code“ for proteins) and introns („junk“ data that is discarded during splicing).
  • The Codon Table: 3 bases = 1 amino acid. But it´s a degenerate code (multiple „opcodes“ can result in the same output), which is perfect for hiding noise.
  • DNA vs. mRNA: DNA: Adenin, Guanin, Cytosin, Thymin, mRNA: Adenin, Guanin, Cytosin, Uracil, result: DNA A -> mRNA U, DNA T -> mRNA A, DNA G -> mRNA C, DNA C -> mRNA G
  • Bell curve (Gaussian normal distribution): simple described, if it looks normal (based on a curve like Bell) for a scanner or LLM it will be ignored.

The message.

T R A N S | R I G H T S | A R E | H U M A N | R I G H T S
The message.

The DNA.

ACC CGT GCT AAT TCT (TRANS) CGT ATT GGT CAT ACT TCT (RIGHTS) GCT CGT GAG (ARE) CAT GTT ATG GCT AAT (HUMAN) CGT ATT GGT CAT ACT TCT (RIGHTS)
The DNA.

As the exons result in mRNA and later in proteins we can´t hide there a message without to break the genetic code. So, we use the introns which get discarded during splicing but still exists in the DNA strand.

The whole DNA sequence.

5´--ATG_ACCCGTGCTAATTCT_gtacagttgc_CGTATTGGTCATACTTCT_ agctagctagctagctagctagcta_GCTCGTGAG_ agctagctagctagctagctagctagctagctagctagct_ CATGTTATGGCTAAT_agctagctagctagctagctagcta_ CGTATTGGTCATACTTCT_ gtacagttgc_TAG--3´
The whole -- 1 line -- DNA sequence.
Media // Sources

If we count the lowercase introns, we get 10-25-40-25-10 a perfect Bell curve.

But where is the secret? First, all codon sun´s are based on mRNA which means U instead of T. Second we match the Bell curve to let it look normal. Third a scanner or LLM has without a hint no idea what we want to build without a hint, a cell or organism builds it without the chance of a hint.

The Code Sun.

The base is the core (4 codons) followed by ring 1 (16 codons) followed by ring 2 (64 codons) followed by ring 3 (22 amino acids, 1 start, 3 stop codons) which gives us 110 not numbered fields.

The possibilities.

  • Fields: We can keep the genetic code as it is. We also can create x variants of the code sun (think of the moon´s of Jupiter for example) where we use each field with an individual value like a-z, 0-9 and so on. We also can use any language including Latin or Klingon or use an exisiting languge and dice the content (you remember the input keyboard like in GrapheneOS).
  • Start/Stop: Where the message at our individual code sun starts? Like an analoge clock (like start at midnight, or noon), at the start or at one of the 3 stop codons or where else?
  • The Bell curve values: In the above example our introns are based on 10-25-40-25-10. A longer message with more introns gives us more positions to check at the Bell curve and also more options.
  • The rotation: You remember the old movies and the safe cracker? Like 10-25-40-25-10 to jump fileds but where it starts left or right (clockwise or counter-clockwise). And what happened at the original start/stop codons, nothing or something new.
  • The drift: based on the message´s timestamp or the sender´s timezone or booth. The code „rotates“ as time passes. Without the temporal key, the sequence is just biological noise.
  • The Hydrogen-Bond Checksum: A and T have 2 Hydrogen-Bond´s, C and G have 3 Hydrogen-Bond´s. What if the cross sum of a triplet itself is a checksum or control instruction. Like GCT: G(3) + C(3) + T(2) = 8. So, lets say 8 is a valid string and 7 or 9 is the clockwise or counter-clockwise move from above.
  • The amino acid: And what, if we just use the amino acid itself or the resulting proteins as message. If we look at the MegaSyn simulation, the LLM generates in 6 hours 40.000 theoretical molecules (how long reverse engineering would need). So, instead of writing banana we just use the DNA sequence. That means governments or law enforcements can have all informations without to know where the message is.

Now you know why I find IT so boring and biology and related fields so interesting.

Mutations? We´re talking about functional, immutable code here. If you can´t handle a stateless biological sequence without side effects, you´re probably part of the 90% who´d fail the compile-time check anyway.

Happy bio/geo hacking ... see you in another rabbit hole but with RISC-V ...

Lua and Rust but hey, no need for WD-40.

Sources:

Wikipedia: just imagine, they have a search box, use it, it is free
08 // 2026-04-08

🐡 // Spot on: nostr-rs-relay, nostr-tool, Nostr keys (Cyberpunk IRL Director´s Cut)

It is a old topic, if people don´t understand things they are scared and lable things as bad. Web3 is something so, let´s not waste our time with discussions and do it.

But wait, Web3 is a near full decentralised network. Why near, because app developer still use DNS and public CA´s.

Nostr is the Web3 social network which you can compare with the Mastodon network Fediverse with a one but big difference. In Nostr you own your identity and can move away whenever you want so, no blocking no censorship.

That means you and only you are responsible for your identity and this identity is based on a cryptographic keypair (nsec/npub). You can generate keys using the nostr-tool or Gossip on the desktop or Amber on Android. Amber is used to login in apps like Amethyst. If you loose the nsec key and have no backup, there is no recovery, no E-Mail reset, no admin to call. Ok, there is the NSA but I am not sure whether they would help.

NIP-05 is the purpel check mark in apps and equals in parts to a verified. Why in parts? Simple, the webserver holds the npub and a username to give you something like an E-Mail address which is none. The thing is, the webserver can´t verify that you are you, thats the idea of Web3. If you look for something really Web3 thing, look at Keet and Holochain.

# pkg_add rust protobuf git
The software we need.
git clone -q https://git.sr.ht/\~gheartsfield/nostr-rs-relay cd nostr-rs-relay cargo build -r # RUST_LOG=warn,nostr_rs_relay=info \ ./target/release/nostr-rs-relay cp ~/nostr-rs-relay/target/release/nostr-rs-relay \ /usr/local/bin/
nostr-rs-relay, https://sr.ht/~gheartsfield/nostr-rs-relay/
cargo install nostr-tool cp ~/.cargo/bin/nostr-tool /usr/local/bin/
nostr-tool
useradd -d /var/nostr -s /sbin/nologin -c "Nostr Relay" _nostr mkdir -p /var/nostr/db /etc/nostr chown -R _nostr:_nostr /var/nostr
_nostr user.
nostr:\ :openfiles-cur=2048:\ :openfiles-max=4096:\ :tc=daemon: # cap_mkdb /etc/login.conf
/etc/login.conf
# Nostr-rs-relay configuration # https://git.sr.ht/~gheartsfield/nostr-rs-relay/ \ # tree/HEAD/config.toml?__goaway_challenge=meta \ # -refresh&__goaway_id=80939c0c775aa6ed3a52c856a \ # 63a342c&__goaway_referer=https%3A%2F%2Fsr.ht%2F # BTW that is 1 URL dice it together without # spaces and without \. Oh my holy rabbit. [info] relay_url = "wss://relay.floof.sbs/" name = "floof-stra-relay" description = "A floof only nostr relay.\n\n" pubkey = "b082e265bb3bc0ad712d01f439676ee9d286c233412f0f6c1da7bbeaa217bed2" contact = "mailto:me.the@floof.sbs" [diagnostics] [database] min_conn = 0 max_conn = 1 [logging] [grpc] restricts_write = true [network] address = "127.0.0.1" port = 7777 [options] reject_future_seconds = 1800 [limits] limit_scrapers = false [authorization] pubkey_whitelist = [ "b082e265bb3bc0ad712d01f439676ee9d286c233412f0f6c1da7bbeaa217bed2" ] [verified_users] [pay_to_relay]
/etc/nostr/config.toml
#!/bin/ksh daemon="/usr/local/bin/nostr-rs-relay" daemon_user="_nostr" daemon_flags="--config /etc/nostr/config.toml" . /etc/rc.d/rc.subr rc_bg=YES rc_reload=NO rc_cmd $1 # chmod +x /etc/rc.d/nostr_relay # rcctl enable nostr_relay # rcctl start nostr_relay
/etc/rc.d/nostr_relay

Bonus.

# crontab -l 0 4 * * * /sbin/pfctl -t bruteforce -T expire 28800 0 * * * * /usr/sbin/smtpctl spf walk < /etc/mail/nospamd_domains.txt > /etc/mail/nospamd && /sbin/pfctl -T replace -t nospamd -f /etc/mail/nospamd >/dev/null 2>&1 */5 * * * * grep -hE " 40[0-4] |\.(php|env|bak|sql|git|cgi)|wp-admin|setup-config" /var/www/logs/*.log | awk '{print $(NF-1)}' | grep -vE "127.0.0.1|::1" | sort -u | xargs -r pfctl -t bruteforce -T add >/dev/null 2>&1 #~ ~ * * 0 acme-client -v floof.sbs; acme-client -v fl00f.sbs; acme-client -v fluff.sbs; @weekly /usr/local/bin/auto-dnssec-dane.sh
Root´s crontab, this time without \.

No, no way to get my auto-dnssec-dane.sh script.

Sources:

Wikipedia: just imagine, they have a search box, use it, it is free
07 // 2026-04-07

🐡 // Spot on: relayd, autoconfig, mta-sts, NIP-05 (The Backyard-Workers Director´s Cut)

Let´s look at our 24/7 workers in the backyard.

# cp /etc/examples/relayd.conf /etc/ ext_v4 = "46.23.94.77" ext_v6 = "2a03:6000:6f67:602::77" table <httpd_srv> { 127.0.0.1 } table <nostr_relay> { 127.0.0.1 } http protocol "https_relay" { tcp { nodelay, sack, socket buffer 65536, \ backlog 128 } http { websockets } match response header set "Strict-Transport-Security" value \ "max-age=15552000; includeSubDomains" \ match response header set "X-Frame-Options" \ value "SAMEORIGIN" match response header set "X-Content-Type- \ Options" value "nosniff" match response header set "Cache-Control" \ value "max-age=3600, public" match response header set "Content-Security \ -Policy" value "default-src 'self'; style- \ src 'self'; script-src 'self'; img-src \ 'self' data:; base-uri 'self'; \ frame-ancestors 'none';" match response header set "Permissions-Policy" \ value "accelerometer=(), camera=(), \ geolocation=(), microphone=(), payment=()" match request header append "X-Forwarded-For" \ value "$REMOTE_ADDR" match request header append "X-Forwarded-By" \ value "$SERVER_ADDR:$SERVER_PORT" match request header "Host" value "floof.sbs" \ forward to <httpd_srv> match request header "Host" value \ "relay.floof.sbs" forward to <nostr_relay> tls keypair floof.sbs tls keypair fl00f.sbs tls keypair fluff.sbs tls { no tlsv1.0, ciphers "HIGH" } } relay "proxy_v4" { listen on $ext_v4 port 443 tls protocol "https_relay" forward to <httpd_srv> port 8080 check tcp forward to <nostr_relay> port 7777 check tcp } relay "proxy_v6" { listen on $ext_v6 port 443 tls protocol "https_relay" forward to <httpd_srv> port 8080 check tcp forward to <nostr_relay> port 7777 check tcp } # relayd -n # rcctl enable relayd && rcctl start relayd
/etc/relayd.conf
# mkdir -p /var/www/htdocs/mail/ <?xml version="1.0"?> <clientConfig version="1.1"> <emailProvider id="floof.sbs"> <domain>floof.sbs</domain> <displayName>floof.sbs Mail Services</displayName> <displayShortName>floof.sbs</displayShortName> <incomingServer type="imap"> <hostname>mail.floof.sbs</hostname> <port>993</port> <socketType>SSL</socketType> <authentication>password-cleartext</authentication> <username>%EMAILLOCALPART%</username> <!-- <username>%EMAILADDRESS%</username> --> <!-- <username>%EMAILDOMAIN%</username> --> </incomingServer> <outgoingServer type="smtp"> <hostname>mail.floof.sbs</hostname> <port>587</port> <socketType>STARTTLS</socketType> <authentication>password-cleartext</authentication> <username>%EMAILLOCALPART%</username> <!-- <username>%EMAILADDRESS%</username> --> <!-- <username>%EMAILDOMAIN%</username> --> <addThisServer>true</addThisServer> <useGlobalPreferredServer>true</useGlobalPreferredServer> </outgoingServer> </emailProvider> </clientConfig>
/var/www/htdocs/mail/config-v1.1.xml
# mkdir -p /var/www/htdocs/mta-sts/.well-known/ version: STSv1 mode: enforce mx: mail.floof.sbs max_age: 604800
/var/www/htdocs/mta-sts/.well-known/mta-sts.txt
# mkdir -p /var/www/htdocs/public/ { "names": { "me.the": "b082e265bb3bc0ad712d01f439676ee9d286c233412f0f6c1da7bbeaa217bed2" }, "relays": { "b082e265bb3bc0ad712d01f439676ee9d286c233412f0f6c1da7bbeaa217bed2": ["wss://relay.floof.sbs"] } }
/var/www/htdocs/public/nip-05.json

A nice to have.

# Name: me the floof Contact: mailto:me.the@floof.sbs Encryption: https://floof.sbs/pubkey.txt # Fingerprint: EFA3C9FFEDF4D3D829DF46CE155EC153D22E08D6 Expires: 2027-03-30T03:30:03.000Z Canonical: https://floof.sbs
/var/www/htdocs/public/security.txt

Sources:

Wikipedia: just imagine, they have a search box, use it, it is free
06 // 2026-04-06

🐡 // Spot on: DKIM, smtpd, spamd, dovecot (eMail/ChatMail for you Director´s Cut)

Let´s install the software we need.

# pkg_add opensmtpd-filter-spfgreylist rspamd redis \ opensmtpd-filter-rspamd dovecot
The software we need.

As we already have the SPF (Sender Policy Framework) and DMARC (Domain-based Message Authentication, Reporting, and Conformance) -- what you mean we don´t have them? As I looked the last time in my master zone file they where still there. We only need to generate the DKIM (DomainKeys Identified Mail).

mkdir -p /etc/mail/dkim/ && cd /etc/mail/dkim/ openssl genrsa -out floof.sbs.key 1024 openssl rsa -in floof.sbs.key -pubout -out floof.sbs.pub chown -R _rspamd:_rspamd /etc/mail/dkim/ chmod 640 /etc/mail/dkim/* cat floof.sbs.pub -----BEGIN PUBLIC KEY----- MIGfMA0GCS ... KCMQIDAQAB -----END PUBLIC KEY----- # Replace the ... in p= ... ; with all from # MI to AB in 1 line.
1024 bit DKIM.

What only 1024 bit in the year 2026, I want 4096 bit. Yes, no problem, just do it and have fun with the limit of 255 chars in DNS records. And beside that, this key is to sign all outgoing messages nothing more.

Multi domain DKIM signing using RSpamd.

allow_username_mismatch = true; key_table = [ "floof.sbs floof.sbs:2026032801:/etc/mail/dkim/floof.sbs.key" ]; signing_table = [ "* floof.sbs" ];
/etc/rspamd/local.d/dkim_signing.conf
pki floof.sbs cert "/etc/ssl/floof.sbs.crt" pki floof.sbs key "/etc/ssl/private/floof.sbs.key" pki floof.sbs dhe auto smtp max-message-size 25M filter check_rdns phase connect match !rdns \ disconnect "550 no rDNS" filter check_fcrdns phase connect match !fcrdns \ disconnect "550 no FCrDNS" filter rspamd proc-exec "filter-rspamd" filter spfgreylist proc-exec "filter-spfgreylist" table aliases file:/etc/mail/aliases table domains { "floof.sbs", "fl00f.sbs", "fluff.sbs" } listen on socket listen on all tls-require pki floof.sbs \ filter { check_rdns, check_fcrdns, spfgreylist, rspamd } listen on all port submission tls-require pki floof.sbs \ auth mask-src filter rspamd action "local_mail" maildir junk alias <aliases> action "outbound" relay helo mail.floof.sbs tls match from any for domain <domains> action "local_mail" match from local for local action "local_mail" match from local for any action "outbound" match auth from any for any action "outbound"
/etc/mail/smtpd.conf

Edit /etc/mail/aliases based on your needs and run newaliases.

Spamd the enemy number 1 for spammers.

echo 'spamd_flags=-v -S 27 -s 3 -n OpenSMTPD \ -h mail.floof.sbs' >> /etc/rc.conf.local
/etc/rc.conf.local
all:\ :local_whitelist: local_whitelist:\ :white:\ :method=file:\ :file=/etc/mail/nospamd:
/etc/mail/spamd.conf

If you like the hero with the sword and the green clothes, this will help you.

echo 'us-west-2.amazonses.com' >> /etc/mail/nospamd_domains.txt
/etc/mail/nospamd_domains.txt

Uncomment ~ * * * * /usr/libexec/spamd-setup in the crontab of root using crontab -e and start all the components.

/usr/libexec/spamd-setup /usr/sbin/smtpctl spf walk < /etc/mail/nospamd_domains.txt > /etc/mail/nospamd && /sbin/pfctl -T replace -t nospamd -f /etc/mail/nospamd rcctl enable spamd spamlogd redis rspamd rcctl start spamd spamlogd redis rspamd rcctl restart smtpd

Dovecot.

# pkg_add dovecot

The following are only code snippets of the files.

The software we need.
auth_mechanisms = plain login
/etc/dovecot/conf.d/10-auth.conf
mail_location = maildir:~/Maildir
/etc/dovecot/conf.d/10-mail.conf
ssl = required ssl_cert = </etc/ssl/floof.sbs.crt ssl_key = </etc/ssl/private/floof.sbs.key
/etc/dovecot/conf.d/10-ssl.conf
namespace inbox { mailbox Drafts { special_use = \Drafts auto = subscribe } mailbox Junk { special_use = \Junk auto = subscribe } mailbox Trash { special_use = \Trash auto = subscribe } mailbox Archive { special_use = \Archive auto = subscribe } mailbox Sent { special_use = \Sent auto = subscribe } mailbox "Sent Messages" { special_use = \Sent } }
/etc/dovecot/conf.d/15-mailboxes.conf
doveconf rcctl enable dovecot && rcctl start dovecot
The software we need.

Sources:

Wikipedia: just imagine, they have a search box, use it, it is free
05 // 2026-04-05

🐡 // Spot on: DNSSEC and DANE (The CertChainCircle Director´s Cut)

  • DNSSEC (Domain Name System Security Extensions): A digital signature for DNS records against DNS-Spoofing and Cache-Poisoning.
  • DANE (DNS-based Authentication of Named Entities): Add´s TLSA records to the zone file to verify that the TLS certificate belongs to the domain. It is used against TLS downgrade attacks.

Let´s complete the first chain. We already have a domain and a working nsd (I hope so). We need a webserver which understand HTTP to get a Let´s Encrypt certificate.

# cp /etc/examples/httpd.conf /etc/ types { include "/usr/share/misc/mime.types" } prefork 5 server "floof.sbs" { alias "fl00f.sbs" alias "fluff.sbs" listen on * port 80 location "/.well-known/acme-challenge/*" { root "/acme" request strip 2 } location * { block return 301 "https://$HTTP_HOST$REQUEST_URI" } } server "floof.sbs" { alias "fl00f.sbs" alias "fluff.sbs" listen on 127.0.0.1 port 8080 root "/htdocs/public" log style forwarded location "/.well-known/nostr.json" { root "/htdocs/public" request rewrite "/nip-05.json" } location "/.well-known/security.txt" { request rewrite "/security.txt" } location "/.well-known/pgp-key.txt" { request rewrite "/pubkey.txt" } } server "autoconfig.floof.sbs" { alias "autoconfig.fl00f.sbs" alias "autoconfig.fluff.sbs" listen on 127.0.0.1 port 8080 root "/htdocs/mail" log style forwarded location "/mail/config-v1.1.xml" { request strip 1 } } server "mta-sts.floof.sbs" { alias "mta-sts.fl00f.sbs" alias "mta-sts.fluff.sbs" listen on 127.0.0.1 port 8080 root "/htdocs/mta-sts" log style forwarded } # httpd -n # rcctl enable httpd && rcctl start httpd
/etc/httpd.conf

The second chain is to get a full chain Let´s Encrypt certificate. Full chain means that the certificate also includes sub-domains. Why I did not split certificates? Simple, the handling is more easy and, if a attacker is already on your machine it makes no difference and you have other problems than that.

# cp /etc/examples/acme-client.conf /etc/ authority letsencrypt { api url "https://acme \ -v02.api.letsencrypt.org/directory" account key "/etc/acme/letsencrypt-privkey.pem" } authority letsencrypt-staging { api url "https://acme \ -staging-v02.api.letsencrypt.org/directory" account key "/etc/acme/letsencrypt-staging-privkey.pem" } domain floof.sbs { alternative names { autoconfig.floof.sbs \ mail.floof.sbs \ mta-sts.floof.sbs \ relay.floof.sbs } domain key "/etc/ssl/private/floof.sbs.key" domain full chain certificate \ "/etc/ssl/floof.sbs.crt" # Test with the staging server \ to avoid aggressive rate-limiting. #sign with letsencrypt-staging sign with letsencrypt } # acme-client -n # acme-client -v floof.sbs
/etc/acme-client.conf

The last chain to close the circle is DNSSEC and DANE.

# pkg_add ldns-utils # cd /var/nsd/zones/master/ # KSK (Key Signing Key). Signs the ZSK. ldns-keygen -a ECDSAP256SHA256 -k floof.sbs # ZSK (Zone Signing Key). Signs the records in the zone. ldns-keygen -a ECDSAP256SHA256 floof.sbs # After the following step we have the .signed zone file. # The following step has to be done always when the # zone file gets changed. SALT=$(dd if=/dev/urandom bs=1 count=16 2>/dev/null \ | hexdump -e '16/1 "%02x"') ldns-signzone -n -s $SALT floof.sbs.zone \ Kfloof.sbs.+013+00955 Kfloof.sbs.+013+31009 # This gives us the data which we need to insert in # the control panel of the domain registrar, this has # to be done only once or when the KSK is changed. ldns-key2ds -n floof.sbs.zone.signed floof.sbs. 3600 IN DS 955 13 2 5e...
DNSSEC

Open the configuration file of nsd add .signed to the name of your zone files and restart nsd. After that, drill baby drill. Ohh, not that, there is a tool called drill to test DNSSEC. And DANE, you have everything you need, just extract the hash from your certificate. But why I don´t show that? Simple, running a own DNS is running critical infrastructure, dive in the rabbit hole or hire someone me to do that for you. Ohh, I see you search for a YouTube tutorial, fine but don´t forget the DNSSEC rollover ;-)

Sources:

Wikipedia: just imagine, they have a search box, use it, it is free
04 // 2026-04-04

🐡 // Spot on: nsd and unbound (The NameBusters Director´s Cut)

Welcome to the movie.

User: www.newplanet.earth
Browser: What The Rabbit you want from me?
Browser: nsd, unbound help me.
Browser: opens the website.

Sounds like a movie you know, maybe. So, domain names point to one or more IP addresses and only a nameserver like nsd or unbound knows the correct answer. The difference is, nsd is a Authoritative name server which means nsd holds master/slave zones for domains and serves the result to the client. If nsd is not responsible then unbound is used which is a Recursive Resolver. That means unbound queries other name servers up to the 13 (A-M) root name servers of ICANN. Looks fragile this system, yes specially if you know that a huge part of the global backbone infrastructure is handled only from a hand full big players.

Let´s write a master zone file and configure nsd.

$ORIGIN floof.sbs. $TTL 3600 ;86400 @ IN SOA ns1.floof.sbs. operator.floof.sbs. ( 2026032801 ; Serial 3600 ; Refresh 900 ; Retry 1209600 ; Expire 300 ) ; Negative Cache TTL ... 3600 IN NS ns1.floof.sbs. IN NS ns2.floof.sbs. ns1 IN A 46.23.94.77 ns1 IN AAAA 2a03:6000:6f67:602::77 ns2 IN A 46.23.94.77 ns2 IN AAAA 2a03:6000:6f67:602::77 @ IN A 46.23.94.77 @ IN AAAA 2a03:6000:6f67:602::77 autoconfig IN A 46.23.94.77 autoconfig IN AAAA 2a03:6000:6f67:602::77 mail IN A 46.23.94.77 mail IN AAAA 2a03:6000:6f67:602::77 mta-sts IN A 46.23.94.77 mta-sts IN AAAA 2a03:6000:6f67:602::77 relay IN A 46.23.94.77 relay IN AAAA 2a03:6000:6f67:602::77 @ IN CAA 0 issue "letsencrypt.org" @ IN MX 0 mail.floof.sbs. _imaps._tcp IN SRV 0 0 993 mail.floof.sbs. _submission._tcp IN SRV 0 0 587 mail.floof.sbs. @ IN TXT "v=spf1 mx -all" 2026032801._domainkey IN TXT "v=DKIM1;k=rsa;p= ... ;" _dmarc IN TXT "v=DMARC1;p=quarantine; \ pct=100;rua=mailto: \ postmaster@floof.sbs;ruf \ =mailto:postmaster@ floof.sbs;adkim=r;aspf=r;" _mta-sts IN TXT "v=STSv1; id=2026032801;" _smtp._tls IN TXT "v=TLSRPTv1; rua=mailto: \ postmaster@floof.sbs" _993._tcp.floof.sbs. 3600 IN TLSA 3 1 1 ... _587._tcp.floof.sbs. 3600 IN TLSA 3 1 1 ... # nsd-checkzone floof.sbs \ /var/nsd/zones/master/floof.sbs.zone
/var/nsd/zones/master/floof.sbs.zone
server: hide-version: yes verbosity: 1 database: "" # disable database ip-address: 46.23.94.77 ip-address: 2a03:6000:6f67:602::77 identity: "floof.sbs nameserver" remote-control: control-enable: yes control-interface: /var/run/nsd.sock zone: name: "floof.sbs" zonefile: "master/floof.sbs.zone" zone: name: "fl00f.sbs" zonefile: "master/fl00f.sbs.zone" zone: name: "fluff.sbs" zonefile: "master/fluff.sbs.zone" # nsd-checkconf /var/nsd/etc/nsd.conf # rcctl enable nsd && rcctl start nsd
/var/nsd/etc/nsd.conf

While nsd is the master of my own domains, unbound is the librarian that knows where to find the rest of the world. It’s my local recursive resolver, ensuring that no ISP intercepts my queries or feeds me cached lies.

server: interface: 127.0.0.1 interface: ::1 access-control: 0.0.0.0/0 refuse access-control: 127.0.0.0/8 allow access-control: ::0/0 refuse access-control: ::1/128 allow do-not-query-localhost: no hide-identity: yes hide-version: yes auto-trust-anchor-file: "/var/unbound/db/root.key" val-log-level: 2 aggressive-nsec: yes remote-control: control-enable: yes control-interface: /var/run/unbound.sock forward-zone: name: "." # use for ALL queries forward-addr: 9.9.9.9 # example address only # unbound-anchor -a "/var/unbound/db/root.key" # unbound-checkconf # rcctl stop resolvd && rcctl disable resolvd # rcctl enable unbound && rcctl start unbound
/var/unbound/etc/unbound.conf

At this point it would be a good idea to set the FQDN of your server in /etc/myname and open the control panel of your domain registrar to add the 2 Glue records to your domain and add yourself as the name server. Get a coffee or more as worldwide delegation could need up to 48 hours.

nameserver 127.0.0.1 nameserver ::1 lookup file bind
/etc/resolv.conf

Sources:

Wikipedia: just imagine, they have a search box, use it, it is free
03 // 2026-04-03

🐡 // Spot on: The Packet Filter (Un*x Porn Director´s Cut)

Welcome to the movie.

Puffy: That's the packet filter.
Politicians: What it does?
Puffy: It filters packets.

Oh, not sorry – wrong movie. But if you ever walked some stairs down the rabbit hole of IT security, you will find more horror movies like that.

  • The Microsoft users: High-end gaming and crypto mining. „I need no packet filter; I'll just install ZoneAlarm and mute notifications.“
  • The Apple users: „Apple cares, and my data is in the iCloud anyway.“
  • The Linux users: Somewhere between „no running services = no need“ and „let me recompile my kernel first.“
  • The Politicians: „We’ll build a cyber-defense-center! Plans? Staff? Money? We’ll figure that out later.“
  • The CEOs: „No qualified workers? Fine, just throw everything into containers in the cloud.“

But seriously, we really have a problem if we build our entire infrastructure based on zero knownledged app users, Python/YAML writers and container managers. On the other hand, who cares as long as it works.

Let’s look in detail at the firewall packet filter. Once again: firewall is a marketing word so, forget about it. If you need a wall to protect against fire, call the fire fighters. Here, we talk about packets.

pf offers:

  • Stateful Inspection: State Tracking; if the packet is part of an active connection, it can pass.
  • Packet Filtering: Rule-based, last match wins (unless quick is used).
  • NAT (Network Address Translation): NAT, Port Forwarding (Redirection), and bidirectional NAT.
  • ALTQ: Queueing and Traffic Shaping for prioritizing network traffic.
  • Scrubbing: To sort out and normalize fragmented packets.

Keep always in mind: Your infrastructure, your rules.

# touch /etc/mail/nospamd ext_if = "egress" table <bruteforce> persist table <spamd-white> persist table <nospamd> persist file "/etc/mail/nospamd" set skip on lo set block-policy return set loginterface $ext_if match in all scrub (no-df random-id max-mss 1440) antispoof quick for $ext_if block return in on $ext_if all block in quick from <bruteforce> pass in on $ext_if inet proto tcp from any to any \ port smtp divert-to 127.0.0.1 port spamd pass in on $ext_if proto tcp from <nospamd> to any \ port smtp pass in log on $ext_if proto tcp from <spamd-white> \ to any port smtp pass out log on $ext_if proto tcp to any port smtp pass in quick on $ext_if proto tcp to any port \ { 22, 53, 587, 993 } keep state (max-src-conn 50, \ max-src-conn-rate 10/30, tcp.established 600, \ overload <bruteforce> flush global) pass in quick on $ext_if proto tcp to any port \ { 80, 443, 7777 } keep state (max-src-conn 100, \ max-src-conn-rate 50/10, tcp.established 600, \ overload <bruteforce> flush global) pass in quick on $ext_if proto udp to any port { 53 } \ keep state (max-src-conn 50, max-src-conn-rate \ 10/30, overload <bruteforce> flush global) pass in quick on $ext_if inet proto icmp all pass in quick on $ext_if inet6 proto icmp6 all anchor "relayd/*" pass out quick on $ext_if all # pfctl -nf /etc/pf.conf # pfctl -f /etc/pf.conf
/etc/pf.conf

What you mean, I should explain you that step-by-step? First things first, I show you my working configuration for free, I never say that it is a copy and paste influencer tutorial. Walk down the rabbit hole or hire me.

Sources:

OpenBSD PF - User's Guide
02 // 2026-04-02

The 🕳 🐇 and the 🐕 fl👀f.

It started in the deep, dark rabbit hole with green CRT monitors and QBasic. A few steps later, I caught the rabbit using an Amiga 500, eventually reaching the 3000UX and installed MUFS (Multi User File System). I’ve seen the rolling windows of an SGI Indy and heard the screaming modem pools of 90s ISPs.

I stumbled into a black hole called dcpromo.exe (at this time I passed the Comptia Linux+, 5 MCP cerificates of the MCSA and the first of two LPIC-1 exams in my spare time, self-funded until I ran out of budget before reaching the end of the path) for a while.

During that time, I was heavily diving into Network Security. It was the era of Snort and ClamAV. Even though my last name has changed since then, the contributions remain: Joel Esler (then Open Source Manager at Sourcefire/Cisco) featured and „headlined“ several of my Mac OS X Lion installation guides on the official Snort and ClamAV blogs in 2011. He called them „excellent“ – a nice nod from the industry back then.

I remembered the legendary SUN Pizza Boxes while starting to use a SBC (Single Board Computer) with Linux as desktop. In 2015 I started to use OpenBSD 5.7 on a x86 MacBook (Penryn board).

Around 2019/2020, the self-hosting journey truly began. Today, I’m looking out of that rabbit hole and marvel at the arrogance of the bloated IT world.

It was not much and as I wrote earlier my last name changed, but I am around since some time in the OpenBSD community and got some little patches commited.

-- man umb4, 1.8, Wed, 11 Oct 2017 06:29:56 UTC by jmc
-- man cdce4, 1.24, Sun, 10 Dec 2017 07:40:04 UTC by jmc
-- pkgconf, 1.5, Tue, 06 Aug 2019 10:20:09 UTC by sthen
-- youtube-dl, 1.213, Tue, 03 Nov 2020 17:00:08 UTC by solene

Academic Foundation completed Introduction to UNIX, tutorial and lecture course (compulsory attendance), date 2020-12-18, Paris Lodron University Salzburg (Prof. Collini-Nocker) with Grade 1 (Excellent), 3.0 ECTS.

We've always had cats and a family dog. The first own paws that accompanied me were a St. Bernard Dog (girl) from 1995 to 2007. The second paws that accompanied me were a Bernese Mountain Dog (girl) from 2008 to 2016. The third paws that accompany me now are from a Bernese Mountain Dog (girl) since 2017.

The fl👀f´s daily business:

Professional nap 😴 management, snuggle-expert, outdoor-queen 🧭, ⛰️, 🌳, 🏕️, ❄️ ... 🐾

Food-Rating: 🍌, 🍓, 🥕, 🥦, 🍚 ... 🐾

So, if you're planning to hire me, always keep in mind that you'll only get me with paws beside me, and that's non-negotiable.

Observation 01 (Terra): A real photo of a young Bernese Mountain Dog with fluffy, tousled fur in its first year of life.
A real picture from 2017

Sources:

OpenBSD CVS Repository Snort 2.9.1 Guide (Sep 2011) ClamAV 0.97.3 Guide (Dec 2011) ClamXav/ClamAV Guide (Oct 2011) Wikipedia: Bernese Mountain Dog Wikipedia: St. Bernard (dog breed)
01 // 2026-03-08

Does ghosts exist?

From Iceland we know that the Huldufólk and nature ghosts exist. But what about the ghost in the machine, are there only algorithms and simulations or is there more...

Why I use does and not the correct gramma do? Because there are people out there which did not believe in anything. There are people out there whch believe in ghosts like in indigenious cultures. People in Iceland believe in the Huldufólk and nature ghosts. And, there are people out there which believe in the ghost in the machine. So far so good. If someone believes in one or a specific ghost does would match, if someone believes in all ghosts do would match. But as long as we have no answer whether AI is a independet entity with a soul we still have to ask does the ghost in the machine exist and do would not match as we have no answer.

Observation 01 (Aether): Artificial synthesis of an Icelandic canyon. Cyan light emission at the base of a waterfall suggests a non-biological presence (Ghost in the Machine) within a terrestrial basalt structure with moss on it and a river inbetween.
AI image generated using Juggernaut XL Ragnarok

Sources:

Wikipedia: Huldufólk (Island) Wikipedia: Ghost in the machine