irc.mills.io
running behind Caddy Layer 4. However I don't terminate TLS at the edge in this case.
@prologic@twtxt.net OH SHIT using this for a protocol like gopher is smart! might have to try that for gemini so i donât have to keep a port open for that
irc.mills.io
running behind Caddy Layer 4. However I don't terminate TLS at the edge in this case.
@bender@twtxt.net Sure! đ
{
...
# Layer 4 Reverse Proxy
layer4 {
# Gopher
0.0.0.0:70 {
route {
proxy <internal_ip>:70
}
}
# IRC (TLS)
0.0.0.0:6697 {
route {
proxy <internal_ip>:6697
}
}
}
}
Haiku gets new malloc implementation, removes Gopher support from its browser
Weâve got the Haiku activity report covering February, and aside from the usual slew of bug fixes and minor improvements, thereâs one massive improvement that deserves attention. waddlesplash continued his ongoing memory management improvements, fixes, and cleanups, implementing more cases of resizing (expanding/shrinking) memory areas when thereâs a virtual memory reservation a ⊠â Read more
Bloody hell đ€Šââïžđ€Šââïž
$ jq -r --arg host "gopher.mills.io" '. | select(.request.host==$host) | "\(.request.client_ip) \(.request.uri) \(.request.headers["User-Agent"])"' mills.io.log-au | while IFS=$' ' read -r ip uri ua; do asn="$(geoip -a "$ip")"; echo "$asn $ip $uri $ua"; done | grep -E '^45102.*' | sort | head
45102 47.251.70.245 /gopher.floodgap.com/0/feeds/democracynow/2015/Oct/14/0 ["Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"]
45102 47.251.84.25 /gopher.floodgap.com/0/feeds/voaheadlines/2014/Mar/09/voanews.com-content-article-1867433.html ["Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"]
45102 47.82.10.106 /gopher.viste.fr/1/OnlineTools/hangman.cgi%3F0692937396569A52972EB2 ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.43"]
45102 47.82.10.106 /gopher.viste.fr/1/OnlineTools/hangman.cgi%3F9657307A96569A52974634 ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.43"]
45102 47.82.10.106 /gopher.viste.fr/1/OnlineTools/hangman.cgi%3FB7571C7896569A529E6603 ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.43"]
45102 47.82.10.106 /gopher.viste.fr/1/OnlineTools/hangman.cgi%3FB75EF81296569A529E6617 ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.43"]
45102 47.82.10.106 /gopher.viste.fr/1/OnlineTools/hangman.cgi%3FC6564ADB96569A5A9E660C ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.43"]
@andros@twtxt.andros.dev Broke on me for having alt-urls I think đ„Č
twtxt---profile-layout: Wrong type argument: char-or-string-p, ("https://aelaraji.com/twtxt.txt" "gemini://box.aelaraji.com/twtxt.txt" "gopher://box.aelaraji.com/0/twtxt.txt")
robots.txt
file. only noticed it because the OpenAI bot was hitting me with a lot of nonsensical requests. here is the list from last month:
(I keep thinking that going back go Gopher or Gemini might be a good idea at this point. They donât care about that, probably. đ«Ł)
EdgeGuard Update:
I am now in a position where Iâm no longer having any ports open on my firewall at the Mills DC. đ„ł All services (Gopher, SMTP, IRC, SSH, HTTP) are being proxied through my edge network đȘ
Thank you, @eapl.me@eapl.me! No need to apologize in the introduction, all good. :-)
Section 3: Iâm a bit on the fence regarding documenting the HTTP caching headers. Itâs a very general HTTP thing, so there is nothing special about them for twtxt. No need for the Twtxt Specification to actually redo it. But on the other hand, a short hint could certainly help client developers and feed authors. Maybe itâs thanks to my distroâs Ngninx maintainer, but I did not configure anything for the Last-Modified
and ETag
headers to be included in the response, the web server just already did it automatically.
The more that I think about it while typing this reply, the more I think your recommendation suggestion is actually really great. It will definitely beneficial for client developers. In almost all client implementation cases Iâd say one has to actually do something specifically in the code to send the If-Modified-Since
and/or If-None-Match
request headers. There is no magic that will do it automatically, as one has to combine data from the last response with the new request.
But I also came across feeds that serve zero response headers that make caching possible at all. So, an explicit recommendation enables feed authors to check their server setups. Yeah, letâs absolutely do this! :-)
Regarding section 4 about feed discovery: Yeah, non-HTTP transport protocols are an issue as they do not have User-Agent
headers. How exactly do you envision the discovery_url
to work, though? I wouldnât limit the transports to HTTP(S) in the Twtxt Specification, though. Itâs up to the client to decide which protocols it wants to support.
Since I currently rely on buckketâs twtxt
client to fetch the feeds, I can only follow http(s)://
(and file://
) feeds. But in tt2
I will certainly add some gopher://
and gemini://
at some point in time.
Some time ago, @movq@www.uninformativ.de found out that some Gopher/Gemini users prefer to just get an e-mail from people following them: https://twtxt.net/twt/dikni6q So, it might not even be something to be solved as there is no problem in the first place.
Section 5 on protocol support: Youâre right, announcing the different transports in the url
metadata would certainly help. :-)
Section 7 on emojis: Your idea of TUI/CLI avatars is really intriguing I have to say. Maybe I will pick this up in tt2
some day. :-)
@eapl.me@eapl.me here are my replies (somewhat similar to Lyseâs and Jamesâ)
Metadata in twts: Key=value is too complicated for non-hackers and hard to write by hand. So if there is a need then we should just use #NSFS or the alt-text file in markdown image syntax

if something is NSFWIDs besides datetime. When you edit a twt then you should preserve the datetime if location-based addressing should have any advantages over content-based addressing. If you change the timestamp the its a new post. Just like any other blog cms.
Caching, Yes all good ideas, but that is more a task for the clients not the serving of the twtxt.txt files.
Discovery: User-agent for discovery can become better. Iâm working on a wrapper script in PHP, so you donât need to go to Apaches log-files to see who fetches your feed. But for other Gemini and gopher you need to relay on something else. That could be using my webmentions for twtxt suggestion, or simply defining an email metadata field for letting a person know you follow their feed. Interesting read about why WebMetions might be a bad idea. Twtxt being much simple that a full featured IndieWeb sites, then a lot of the concerns does not apply here. But thatâs the issue with any open inbox. This is hard to solve without some form of (centralized or community) spam moderation.
Support more protocols besides http/s. Yes why not, if we can make clients that merge or diffident between the same feed server by multiples URLs
Languages: If the need is big then make a separate feed. I donât mind seeing stuff in other langues as it is low. You got translating tool if you need to know whats going on. And again when there is a need for easier switching between posting to several feeds, then itâs about building clients with a UI that makes it easy. No something that should takes up space in the format/protocol.
Emojis: Iâm not sure what this is about. Do you want to use emojis as avatar in CLI clients or it just about rendering emojis?
Simplified twtxt - I want to suggest some dogmas or commandments for twtxt, from where we can work our way back to how to implement different feature like replies/treads:
Itâs a text file, so you must be able to write it by hand (ie. no app logic) and read by eye. If you edit a post you change the content not the timestamp. Otherwise it will be considered a new post.
The order of lines in a twtxt.txt must not hold any significant. The file is a container and each line an atomic piece of information. You should be able to run
sort
on a twtxt.txt and it should still work.Transport protocol should not matter, as long as the file served is the same. Http and https are preferred, so it is suggested that feed served via Gopher or Gemini also provide http(s).
Do we need more commandments?
iirc in twtxt v2 it starts prohibited
This is not true. There are no issues supporting fetching feeds via Gemini/Gopher. This is totally fine. What will likely happen is ârecommendationsâ and âdrawbacks of using Gemini/Gopherâ
âFu*** IRC maaan, all the cool kids are on Discord! IRC sucksâ
LOL, Now substitute IRC and Discord with Gopher/Gemini
and Web
.
I hope you get the joke đ
@prologic@twtxt.net does that include mine? otherwise it would make them 8 and 5, maybe even throw off your maths by 0.00001% đ ⊠and, come on! 1.04% seems like a good ratio considering how many gopher holes and gem capsules compared to how many Web servers out there in the world đ
Gemini/Gopher Twtxt feeds account for less than 1% in existence:
$ total=$(inspect-db yarns.db | jq -r '.Value.URL' | awk -F'//' '{if ($1 ~ /^https?/) print "http/https:"; else print $1}' | sort | uniq -c | awk '{sum+=$1} END {print sum}'); inspect-db yarns.db | jq -r '.Value.URL' | awk -F'//' '{if ($1 ~ /^https?/) print "http/https:"; else print $1}' | sort | uniq -c | awk -v total="$total" '{printf "%d %s %.2f%%\n", $1, $2, ($1/total)*100}' | sort -r
7 gemini: 0.66%
4 gopher: 0.38%
1046 http/https: 98.96%
(#bqor23a)
. Its the same one. My pod doesn't have the Root Twt: https://twtxt.net/twt/bqor23a => 404 Not Found.
Oh, and I think I said this before, but just in case, fuck Gemini. Hell, fuck Gopher too. Bring on telnet, and UCCP. đ
@quark@ferengi.one Mine is a little overkill đ but I need to do something for practice:
#!/bin/bash
set -e
trap 'echo "!! Something went wrong...!!"' ERR
#============= Variables ==========#
# Source files
LOCAL_DIR=$HOME/twtxt
TWTXT=$LOCAL_DIR/twtxt.txt
HTML=$LOCAL_DIR/log.html
TEMPLATE=$LOCAL_DIR/template.tmpl
# Destination
REMOTE_HOST=remotHostName # Host already setup in ~/.ssh/config
WEB_DIR="path/to/html/content"
GOPHER_DIR="path/to/phlog/content"
GEMINI_DIR="path/to/gemini-capsule/content"
DIST_DIRS=("$WEB_DIR" "$GOPHER_DIR" "$GEMINI_DIR")
#============ Functions ===========#
# Building log.html:
build_page() {
twtxt2html -T $TEMPLATE $TWTXT > $HTML
}
# Bulk Copy files to their destinations:
copy_files() {
for DIR in "${DIST_DIRS[@]}"; do
# Copy both `txt` and `html` files to the Web server and only `txt`
# to gemini and gopher server content folders
if [ "$DIR" == "$WEB_DIR" ]; then
scp -C "$TWTXT" "$HTML" "$REMOTE_HOST:$DIR/"
else
scp -C "$TWTXT" "$REMOTE_HOST:$DIR/"
fi
done
}
#========== Call to functions ===========$
build_page && copy_files
url
field in the feed to define the URL for hashing. It should have been the last encountered one. Then, assuming append-style feeds, you could override the old URL with a new one from a certain point on:
I was not suggesting to that everyone need to setup a working webfinger endpoint, but that we take the format of nick+(sub)domain as base for generating the hashed together with the message date and content.
If we omit the protocol prefix from the way we do things now will that not solve most of the problems? In the case of gemini://gemini.ctrl-c.club/~nristen/twtxt.txt
they also have a working twtxt.txt at https://ctrl-c.club/~nristen/twtxt.txt
⊠damn I just notice the gemini.
subdomain.
Okay what about defining a prefers protocol as part of the hash schema? so 1: https , 2: http 3: gemini 4: gopher ?
# follow_notify = gemini://foo/bar
to your feedâs metadata, so that clients who follow you can ping that URL every now and then? How would you even notice that, do you regularly read your gemini logs? đ€
@movq@www.uninformativ.de @prologic@twtxt.net Hey! I may have found a silly trick to announce my following to people hosting their feeds on the Gemini space using the requested URI
itself instead of relaying on the USER Agent
đ. Iâve copied my current feed over to my (to be) Gemlog for testing. And if I do a jenny -D "gemini://gem.aelaraji.com/twtxt.txt?follower=aelaraji@https://aelaraji.com/twtxt.txt"
and this happens:
A) As a follower, I get the feed as usual.
B) As the feed owner, I get this in logs:
hostname:1965 - âgemini://gem.aelaraji.com/twtxt.txt?follower=aelaraji@https://aelaraji.com/twtxt.txtâ 20 âtext/plain;lang=en-USâ
You could do the same for Gopher feeds but only if you want to announce yourself by throwing in an error in their logs, then youâll need a second request to fetch the feed. jenny -D "gopher://gopher.aelaraji.com/twtxt.txt&follower=aelaraji@https:/aelaraji.com/twtxt.txt"
gave me this :
gopher.aelaraji.com:70 - [09/Sep/2024:22:08:54 +0000] âGET 0/twtxt.txt&follower=aelaraji@https:/aelaraji.com/twtxt.txt HTTP/1.0â 404 0 ââ âUnknown gopher clientâ
NB: the follower=...
string wonât appear in gopher logs after a ?
but if I replace it with a +
or a &
and it works. There will be a missing /
after the https:
. Probably a client thing.
I would say gopher has a decade left
Wait a minute! Nyxt browser can surf gopher, gemini aaaaaand http!? đČ
I suspect that people who came to Gemini from Gopher are more satisfied with the protocol than people who came to Gemini from HTTP.
I would love to see a world where ones twtxt feed is defined by webfinger. So @xuu@txt.sour.is
=> https://text.sour.is/user/xuu/twtxt.txt
Then my identity can exist independent of the feed location. And I can host multiple protocol types for my feed. Ie. http/gopher/Gemini/irc DCC/etc
Je suis en plein rĂ©flexion. Je cherche Ă me dĂ©connecter, et lire hors ligne aprĂšs synchronisation. Un peu comme le fait offpunk. Cependant, ça ne me convient pas, la navigation en ligne revient trop vite; Je veux rĂ©cupĂ©rer les changements des sites puis les lire. RSS/ATOM (mastodon en gĂ©nĂšre), câest parfait pour ça, je lis tout avec rss2email. Comment faire de mĂȘme pour #gemini et #gopher? Je rĂȘve dâouvrir mon terminal, puis de parcourir les nouveautĂ©s sans clics
Commentaire du code pour un service de lecture over ssh (et je me la pĂšte au passage avec plein de liens #C ) : https://si3t.ch/log/2023-11-13-txtoverssh.c.txt gopher://si3t.ch/0/log/2023-11-13-txtoverssh.c.txt gemini://si3t.ch/log/2023-11-13-txtoverssh.c.txt http://6gvb6fzoxv72mtlpvr2fgj7ytpeggwuerdawspt24njlkwfxir6jncid.onion/log/2023-11-13-txtoverssh.c.txt gopher://of2w2p5f4hsslk63hmo6tid6r7inhlxuxviq4pb5cxg45enswpbrfjad.onion/0/log/2023-11-13-txtoverssh.c.txt gemini://b2khgkvb2wn4avjshjp63kknsjwikgwff5dwwydldia6qwf4kdnueyad.onion/log/2023-11-13-txtoverssh.c.txt ou encore âssh lire@si3t.châ numĂ©ro 45.
Did you know #w3m support gopher:// links?
Et voilĂ , je me suis dĂ©cidĂ© Ă publier mes marques pages aprĂšs un peu de tri. Il y en aura dâautres Ă lâavenir, petit Ă petit, car il y a certainement encore des trucs Ă dĂ©couvrir (sous gopher par exemple) et dâautres que jâai oubliĂ© : https://si3t.ch/pub/public_bookmarks.txt
Check out the Nex Protocol. Itâs designed to be even simpler than Gemini and Gopher. What do you think? Could be great to host a twtxt feed on.
Question to all you Gophers out there: How do you deal with custom errors that include more information and different kinds of matching them?
I started with a simple var ErrPermissionNotAllowed = errors.New("permission not allowed")
. In my function I then wrap that using fmt.Errorf("%w: %v", ErrPermissionNotAllowed, failedPermissions)
. I can match this error using errors.Is(err, ErrPermissionNotAllowed)
. So far so good.
Now for display purposes Iâd also like to access the individual permissions that could not be assigned. Parsing the error message is obviously not an option. So I thought, I create a custom error type, e.g. type PermissionNotAllowedError []Permission
and give it some func (e PermissionNotAllowedError) Error() string { return fmt.Sprintf("permission not allowed: %v", e) }
. My function would then return this error instead: PermissionNotAllowedError{failedPermissions}
At some layers I donât care about the exact permissions that failed, but at others I do, at least when accessing them. A custom func (e PermissionNotAllowedError) Is(target err) bool
could match both the general ErrPermissionNotAllowed
as well as the PermissionNotAllowedError
. Same with As(âŠ)
. For testing purposes the PermissionNotAllowedError
would then also try to match the included permissions, so assertions in tests would work nicely. But having two different errors for different matching seems not very elegant at all.
Did you ever encounter this scenario before? How did you address this? Is my thinking flawed?
@logout@i-logout.cz well done on 1337 days of gopher server uptime
@prologic@twtxt.net Itâs called âcgodâ and it isnât written in C or Go? I want my money backâŠ
I also like Gopher more than Gemini. The problem Gemini is trying to solve is better solved by just writing static HTML 4.01 pages.
@fastidious@arrakis.netbros.com the things Gemini has going for it are mutual TLS and lack of JavaScript. Which makes for a secure albeit boring experience (much like gopher). The fake markdown is a bit of a drag.
A render mode for Gemini probably wouldnt be too hard. There are markdown to Gemini libs out there.
With Web3 the whole trust a 3rd party browser ext + high fees + env impact for compute and storage are serious no gos for me.. I have heard one too many horror stories about clicking the wrong link and some script draining your metamask wallet.
Z7 is a new CC0-licensed 6x7 monospaced typeface for uxn environments. Itâs designed to be an alternative to the specter8-frag font used in various uxn tools https://sectordisk.pw/?sectors&s=1958 gopher://sectordisk.pw:70/0/cgi-bin/sector.cgi?1958
@prologic@twtxt.net that seems to match my numbers. are you picking up the few gophers out there?
kinda makes me wonder about the ~300k you have cached. yâall got the library of alexandria over there.
@prologic@twtxt.net yeah it reads a seed file. Iâm using mine. it scans for any mention links and then scans them recursively. it reads from http/s or gopher. i donât have much of a db yet.. it just writes to disk the feed and checks modified dates.. but I will add a db that has hashs/mentions/subjects and such.
btw my main feed is on gopher now too gopher://tilde.team/0/~dgy/twtxt.txt
@lyxal@twtxt.net @prologic@twtxt.net yah. the service can have a flag for allowing non-TLS for development. but by default ignores.
are there some users that use alternative protos for twtxt? like ftp/gopher/dnsfs đ€
Can I interest you in the latest edition of Tales From The Dork Web when itâs about Gopher, Gemini and The Smol Internet? https://thedorkweb.substack.com/p/gopher-gemini-and-the-smol-internet
Thinkin I might quit twtxt and gemini, tidy up a bit,just use tilde club web, or gopher.
gopher://gopher.club
lynx gopher://tildecow.com:70/
New post on my Gopher site. Back to updating it once a month.
@kas@enotty.dk I like your gopher serverâs formatting, nice and clean and how did you implement the TLS certificate?
@kas@enotty.dk [re: gopher client] If you happen to be on Windows, then Gopher Browser for Windows by Matt Owen is pretty nice, otherwise I use Lynx indeed for gopher.
Enjoying the constraints of the Gopher protocol as a minimalistic zen-mode kind of online publishing revival.
@mdom@domgoergen.com The news site at gopher://taz.de:70/ is really cool. How did you make it?
My gopher site is about 38K big - still plenty of space left on the 1.24MB floppy disk
Updated my daily journal at gopher://gopher.johanbove.info:70/notes
Mirrored on gopher://gopher.johanbove.info/0/twtxt.txt
@davebucklin@davebucklin.com Welcome to the IndieWeb! Thanks also for introducing me to #twtxt. Gophering this for sure.
@reednj@twtxt.reednj.com @mdom@domgoergen.com @durcheinandr@durcheinandr.de gopher doesnât have zombo.com