Sign in

Stefano on littleFedi

@stefano
@stefano

It's me, Stefano, the BSD and illumos Cafe Barista.

I'm testing something cool - littleFedi!

This instance is efficiently running on a Raspberry PI Zero W, powered by NetBSD.

Let's go!

218 posts
hidden followers
hidden following
Pinned posts
The Raspberry PI 0 W, NetBSD, powering this instance
The Raspberry PI 0 W, NetBSD, powering this instance

LittleFedi: light, yet complete

I'm writing this post from a Raspberry Pi Zero W - 512 MB RAM, single-core ARMv6 - running NetBSD, powered by littleFedi. The process sits at 33 MB RSS, CPU basically asleep:

load averages:  0.05,  0.08,  0.09
CPU states:  0.0% user,  0.0% nice,  0.0% system,  1.0% interrupt, 99.0% idle
Memory: 301M Free
  PID COMMAND             RES STATE
 2082 littlefedi-armv6    33M kqueue

No Redis. No PostgreSQL (but optional). No Sidekiq. No Node.js build pipeline. One statically-linked binary, one SQLite file, and the full fediverse experience. And this is the part people tend to miss: the same binary that runs happily on a Pi Zero scales, on the right hardware, to numbers that have nothing to do with "lightweight". It's not a toy that stays a toy. It's built to grow when you need it to.

What LittleFedi actually ships

Federation - Full ActivityPub S2S: WebFinger, NodeInfo 2.1, host-meta, HTTP Signatures with anti-impersonation checks. Per-user and shared inboxes, outbox, followers, following, featured collections. Thread completion with bounded on-demand fetching of missing ancestors/replies (separate sync and background budgets, all hard-capped). Quote posts via FEP-044f with the full approval handshake (QuoteRequest -> QuoteAuthorization), matching Mastodon 4.4 semantics, plus _misskey_quote and Fedibird quoteUri aliases. Account migration (Move), both outgoing and incoming, with alsoKnownAs linking, automatic follower migration, follow import from AP collections, and CSV export/import. Remote interaction discovery - async like/boost resolution from origin servers with REST fallback.

Mastodon API - Broad coverage: timelines (home, public, local, hashtag, bubble, direct), status CRUD with edits, scheduled posts, polls, bookmarks, lists (with replies_policy and exclusive), filters v2 (keyword CRUD), featured tags, followed hashtags (posts appear in home), markers, conversations, notifications with type exclusion, follow requests, blocks (federated Block/Undo), mutes with duration/expiry and hide_notifications, per-user domain blocks. OAuth2 with app registration, authorization code, client credentials and refresh_token flows, PKCE, consent screen, and scope enforcement (read/write/admin:read/admin:write). It talks fine to Elk, Tusky, Ivory, Phanpy, Semaphore and MastoBlaster.

Streaming - WebSocket and SSE. In-process pub/sub hub with per-connection send buffers, zero cost when no client is connected. Broadcast streams for public, local, remote, hashtags and lists. Per-account streams for user timeline, notifications and direct messages. Optional PostgreSQL LISTEN/NOTIFY backend for cross-process fan-out. Mastodon-compatible event serialization.

Push notifications - Full Web Push / VAPID (RFC 8030/8291) with aes128gcm encryption. Per-type alert toggles (mention, follow, reblog, favourite, poll, follow_request, status). Notify-bell support on followed accounts. Subscription expiry detection, rate-limit handling, 5-retry delivery.

Media pipeline - Upload processing: thumbnail generation (600x600), blurhash computation, EXIF stripping, magic-byte validation, SVG rejection, MIME mismatch detection, UUID-based file renaming. Size limits (40 MB default), pixel caps (16 MP default, tunable down to 4 MP for SBCs).

Media privacy proxy - This is the part I actually care about most. All remote media streams through the instance via HMAC-signed URLs (/proxy/media?url=...&sig=...), so local users never expose their IP address to remote servers. SSRF-guarded: DNS resolution check, private/CGNAT IP rejection, redirect re-validation. Pure io.Copy pass-through, no disk, no decode, ~32 KB buffer. Forwards HTTP Range requests for audio/video seeking. Configure a proxy_secret for stable URLs across restarts. On low-RAM devices, set cache_remote = "off" and you still see every image on the fediverse, the instance just doesn't store or process them.

Remote media caching - Three modes: off, eager (background sweep caches all remote attachments, avatars, headers and emoji, backfills existing on mode switch), lazy (cache on first access). Content-addressed, deduplicated by origin URL. Age-based pruning with file GC. Negative-cache for permanently dead URLs. Transparent origin fallback on cache miss. Open Graph preview cards stored durably with posts.

S3-compatible storage - A separate build tag (-tags s3), deliberately excluded from the default binary to keep it small. Supports AWS S3, MinIO, SeaweedFS, Ceph, Backblaze B2, Wasabi, DigitalOcean Spaces. Native media migration CLI: littlefedi admin media storage-migrate between local and S3 (DB-queue-backed, resumable, bounded batches). storage-status, storage-cancel, storage-resume commands. storage-manifest for rclone JSONL integration.

Markdown posts - Powered by goldmark with GFM extensions: tables, strikethrough, bare URL autolinking, hard wraps. Raw HTML deliberately not rendered. Output sanitized through bluemonday (defense-in-depth). Composer toggle in the web UI. Federates source.mediaType: text/markdown (Pleroma/GTS convention). Inbound Markdown source is rendered to HTML.

Visibility modes - The standard four (public, unlisted, private, direct) plus local-only (local, instance timeline only, never federates) and local unlisted (local_unlisted, followers only, no federation). Useful for notes to your own instance community.

Bubble timeline - Curated set of instances whose posts appear alongside local posts in a special timeline. Akkoma-compatible extension. Admin panel for adding/removing bubble instances. API endpoint at /api/v1/timelines/bubble.

Moderation - Account states: suspended (tombstone, federates Delete(Person)), silenced (visible to followers only, dropped from public timelines), quiet (like silenced plus it downgrades federation to followers-only, a middle ground I haven't seen anywhere else), disabled (cannot log in, content stays visible). Self-suspend prevention, last-admin-demotion guard. Blocks (bidirectional, federated), mutes (local-only, with duration and hide_notifications), per-user domain blocks (distinct from admin instance-wide blocks). Reports pipeline: user submissions plus inbound/forwarded Flag into an admin triage UI with resolution actions. Admin notification on new reports. Domain blocks with severity (noop/silence/suspend) plus Mastodon-parity options (reject_media enforced in the proxy, reject_reports, obfuscate, public). A moderation audit log records every admin action.

Web UI - Server-rendered HTML with html/template, templates embedded via //go:embed. Inline CSS (dark mode, Inter font, gradients). htmx 2.x and Alpine.js for progressive enhancement. No build step, no Webpack, no Tailwind, no npm. Every action works as a plain form POST without JavaScript. Works in Lynx, eLinks, text-only browsers, and on mobile.

Full feature set: home/public/local/bubble timelines with infinite scroll, profile pages with follow/unfollow/bell toggle, status threads with reply composer and background thread completion, post creation with CW, visibility selector (6 modes), media upload with alt text, Markdown toggle, quote posts (pre-loads composer with the quoted post as an inline card), post editing, composer autocomplete for @mentions and #hashtags, settings (display name, bio, password, sessions, moderation, pruning, account move, timeline preferences), report form, search page, tag management.

Admin panel - Dashboard (user counts, pending approvals, unreachable instances, open reports), accounts (with suspend/silence/quiet/disable/approve/reject actions), invites (CRUD), domain blocks (with severity and options), reports (triage and resolution), audit log, instance health (per-instance status with follower/following counts, reachability tracking, purge with typed-domain confirmation), bubble instances, settings, housekeeping (on-demand pruning), queue console (ready/scheduled/running/failed by job kind), media storage (S3 migration controls in S3 builds).

Background jobs - DB-backed queue that survives restarts, 8 job kinds: inbox, delivery (16 attempts over roughly 26h with capped exponential backoff and equal jitter), push_notification, actor_refresh, poll_close, scheduled_status, media_cache, media_migration. Per-instance circuit breaker suspends delivery at backoff_count >= 10. Actor refresh dispatcher with stale-while-revalidate, crash-safe leases, and per-actor exponential backoff.

Backups - Periodic or on-demand, server-side, no external tooling required. Each run produces a timestamped directory with config.toml, a portable database dump (VACUUM INTO for SQLite, pg_dump for PostgreSQL), an optional copy of owned media, and a manifest. Toggle it on, set an interval (24h, 7d, whatever fits), decide whether to include owned media (the remote cache is always excluded, no point backing up other people's content), and set a retention count so old backups get pruned automatically. Off by default, one line to turn on.

Housekeeping - Automated pruning: remote statuses by age, own low-interaction statuses (per-user or server thresholds, min likes/boosts caps), tombstones, expired mutes, stale media (>24h unattached), orphaned media (deleted posts), unreferenced media files (disk files with no DB record), cached media by age, cache file GC. On-demand controls in the admin UI.

Security - Token-bucket rate limiting per IP. Security headers: X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Strict-Transport-Security. Content-Security-Policy with nonce-based script/style. CORS. CSRF on all cookie-authenticated POSTs. Session fixation protection. Password reset token in a cookie, not the URL. OAuth consent screen (not auto-issuing). SSRF protection (DNS, IP and redirect re-validation) on all outbound HTTP. HTTP Signature algorithm enforcement (rsa-sha256 only). Inbox body size limit (1 MB). Backfill goroutine cap. Thread-fetch amplification limits. File upload validation (magic bytes, SVG rejection, MIME mismatch). Username enumeration hardening.

Operational - Prometheus metrics at /metrics (counters for API/inbox/fed/web requests, statuses, deliveries, thread fetches, queue depth; gauges for workers, pending follows, uptime). Health checks (/health, /readyz). CLI: admin create-user, admin set-admin, admin list-users, admin suspend/unsuspend, admin invite generate/list/revoke, admin media prune/prune-orphans/prune-files, admin media storage-migrate/status/cancel/resume/manifest, post (publish from stdin/file with Markdown, visibility, CW, media, reply, quote), migrate (run migrations only). SMTP for password reset and notifications (falls back to stdout). Config via TOML file plus environment variables (LITTLEFEDI_{SECTION}_{KEY}).

Platform support - CGO-free, compiles with CGO_ENABLED=0. 23+ GOOS/GOARCH combos via the modernc SQLite driver: macOS (amd64, arm64), Linux (386, amd64, arm, arm64, loong64, ppc64le, riscv64, s390x), FreeBSD (386, amd64, arm, arm64), Windows (386, amd64, arm64), OpenBSD (amd64, arm64). NetBSD (amd64, arm, arm64) via a WASM-based fallback SQLite driver, I don't think anything else in the fediverse space explicitly targets NetBSD. PostgreSQL is a separate build tag (-tags postgres), S3 is another (-tags s3). The default binary carries neither, keeping it small. ARMv6 (GOARM=6) gets special treatment in the release naming, that's the Pi Zero target.

Why it matters

The fediverse shouldn't demand a beefy VPS. It shouldn't require Docker, 2 GB of RAM, Redis, Sidekiq, or a JS toolchain that pulls in 800 packages. A 10 euro Raspberry Pi Zero W running NetBSD, sitting on a shelf, drawing less than 2 watts, can be a fully functional fediverse instance with a web UI, mobile app compatibility, streaming, push notifications, quote posts, account migration, and a moderation toolkit. That's not hypothetical, that's what this post is running on.

But don't mistake "runs on a Pi Zero" for "only runs on a Pi Zero". Point the same binary at real hardware and it scales to numbers that have nothing to do with hobby-instance territory. Low power is the floor, not the ceiling.

One binary, one config file, one SQLite database. Light, yet complete.

I've been involved in this project for a while now, though I can't say much more about it at the moment, there are other people involved besides me and it's not entirely my call to talk about it publicly yet.

#Fediverse #littleFedi #OwnYourData #NetBSD

stefano
Jul 1 Public en edited

Ok, I'm testing something cool.

A blend of #snac, #Mastodon, #honk, #GoToSocial...and more.

This is running on a Raspberry PI Zero W, powered by NetBSD. The same that is powering my own smart thermostat. And it's quick.

I'll use this account and try to "stress" it.

Own your data. Always own your data!

#littleFedi #OwnYourData #Fediverse #NetBSD #RunBSD

Replying to @hkz@chinwag.org
stefano
27m Public en

@hkz@chinwag.org this is what I'm currently seeing, too. Not reassuring at all.

gyptazy
gyptazy
@gyptazy @gyptazy.com
23h Public
Most nodes at @BoxyBSD@bsd.cafe are now operated by #bhyve on #FreeBSD via #Sylve again! Thanks to @hayzam@bsd.cafe for his incredible work by crafting #Sylve! As it’s not that easy to drain nodes to be reinstalled with FreeBSD, there’re still nodes serving VPS instances via #Proxmox / #KVM.

#RUNBSD #VPS #freevps #opensource #community
stefano
9h Public en

Like last years, it seems that the crickets love getting inside our house. I can hear one of them under the fridge. I think if it’s a place he likes, he can stay there for the night.

stefano
Stefano Marinelli
@stefano @bsd.cafe
15h Public
My new Lora device, sitting in a corner of the balcony
My new Lora device, sitting in a corner of the balcony

I think I need a better antenna. And enclosure, I guess

#Meshcore

stefano
Stefano Marinelli
@stefano @bsd.cafe
19h Public
A boxed WiFi LoRa 32 V4 development board in transparent plastic packaging, with a bright blue label showing the board, Bluetooth, Wi-Fi and LoRa symbols, and support for the 863–928 MHz LoRa band.
A boxed WiFi LoRa 32 V4 development board in transparent plastic packaging, with a bright blue label showing the board, Bluetooth, Wi-Fi and LoRa symbols, and support for the 863–928 MHz LoRa band.

Let the fun begin…

“Is there anybody out there?”

#Meshcore

stefano
23h Unlisted en
stefano
1d Public en

I'm getting more and more interested in #MeshCore and #Meshtastic - in the rabbit hole. Thank you, @_elena@mastodon.social ... 😠 😆

richard
ElPerroNegro GoToSocial
@richard @epn.life
1d Public

Just installed Solar Assistant on a Raspberry Pi Zero 2 W and for the first time I think I am understanding my solar set up. Good piece of software this.

https://solar-assistant.io/

#solar #selfhosting #software

stsp
Stefan Sperling
@stsp @bsd.network
1d Public

I have published my initial #OpenBSD #WPA3 implementation.

Thanks to @nlnet for supporting this effort.

Cc @vanhoefm

marc.info/?l=openbsd-tech&m=17

Replying to @poes@sok.egois.org
stefano
1d Public en

@poes@sok.egois.org it shouldn't be too far from being released!

kibcol1049
Col
@kibcol1049 @mstdn.social
1d Public

I think I'll set my Wi-Fi password to 2444666668888888. That way, when guests ask, I can honestly say it’s 1-2-3-4-5-6-7-8. So clever of me!

salvatorelasorella
Salvatore Lasorella
@salvatorelasorella @mastodon.uno
1d Public
Floppy Disk Drive
Floppy Disk Drive

18 luglio 1972

Viene registrato il brevetto del Floppy Disk Drive, nato da un progetto IBM avviato nel 1967 per i mainframe System/370. Sviluppato sotto la guida di David L. Noble e Alan Shugart, il primo floppy da 8 pollici offriva circa 80 KB di capacità. Negli anni successivi questa tecnologia rivoluzionò l'archiviazione dei dati, diventando uno dei simboli dell'informatica personale per oltre vent'anni.

@computer

Replying to @joany@bsd.cafe
stefano
1d Public en

@joany@bsd.cafe it builds but, to be honest, we didn't test it (yet)

Replying to @luca@sironi.xyz
stefano
1d Public en

@luca@sironi.xyz I love this song. Thank you for sharing it!

Replying to @packet@bsd.cafe
stefano
1d Public en edited

@packet@bsd.cafe it will be released and will compile (it already does) for all the GO supported architectures.

At the moment littleFedi is able to pre-build binaries for 43 platform variants (all CGO_ENABLED=0, statically linked). ARM targets include both armv6 and armv7 variants.

AIX

  • littlefedi-aix-ppc64

Android

  • littlefedi-android-arm64

Darwin (macOS)

  • littlefedi-darwin-amd64
  • littlefedi-darwin-arm64

DragonFly BSD

  • littlefedi-dragonfly-amd64

FreeBSD

  • littlefedi-freebsd-386
  • littlefedi-freebsd-amd64
  • littlefedi-armv6-freebsd-arm
  • littlefedi-armv7-freebsd-arm
  • littlefedi-freebsd-arm64

Illumos

  • littlefedi-illumos-amd64

Linux

  • littlefedi-linux-386
  • littlefedi-linux-amd64
  • littlefedi-armv6-linux-arm
  • littlefedi-armv7-linux-arm
  • littlefedi-linux-arm64
  • littlefedi-linux-loong64
  • littlefedi-linux-mips
  • littlefedi-linux-mips64
  • littlefedi-linux-mips64le
  • littlefedi-linux-mipsle
  • littlefedi-linux-ppc64
  • littlefedi-linux-ppc64le
  • littlefedi-linux-riscv64
  • littlefedi-linux-s390x

NetBSD

  • littlefedi-netbsd-386
  • littlefedi-netbsd-amd64
  • littlefedi-armv6-netbsd-arm
  • littlefedi-armv7-netbsd-arm
  • littlefedi-netbsd-arm64

OpenBSD

  • littlefedi-openbsd-386
  • littlefedi-openbsd-amd64
  • littlefedi-armv7-openbsd-arm
  • littlefedi-openbsd-arm64
  • littlefedi-openbsd-ppc64
  • littlefedi-openbsd-riscv64

Plan 9

  • littlefedi-plan9-386
  • littlefedi-plan9-amd64
  • littlefedi-armv6-plan9-arm
  • littlefedi-armv7-plan9-arm

Solaris

  • littlefedi-solaris-amd64

Windows

  • littlefedi-windows-386.exe
  • littlefedi-windows-amd64.exe
  • littlefedi-windows-arm64.exe

#littleFedi

stefano
1d Public en

"What do we have that AI doesn't, and why will it never have it? Artificial intelligence does not die. Therefore, it lacks that awareness of human finiteness, because we all confront our own end. It has no awareness of the end, it knows neither love nor pain.
If it did, it would become a human being.

Dacia Maraini

WeirdWriter
Robert Kingett
@WeirdWriter @caneandable.social
2d Public

If you can, make sure to edit your original post instead of posting the correction in another post in the thread. I see so many people boost the original post but since it wasn't edited, the edited information is more, often times, lost. Editing isn't a bad thing at all, despite what some #Fediverse users tell you. The way federation works, your correction might not even make it to all the instances. Editing is common on most third party apps too. Editing makes you more trustworthy in my eyes. I love the edit functionality, and I am old enough to remember when Fedi nearly flipped it's shit in a negative way when the feature was first proposed. It's the best feature we have. Use it! #FediTips

stefano
2d Public en

I was hearing strange sounds in the room; it was a cricket that had come in. I kindly brought it back to the garden. Now I hear the same sound again…

tg9541
Thomas
@tg9541 @mas.to
2d Public
A countryside road leading to a village. Forest and fields in the morning sun all around. Blue sky with white clouds.
A countryside road leading to a village. Forest and fields in the morning sun all around. Blue sky with white clouds.

My morning bike-commute yesterday. Sure, I could have taken the 10 miles option but the 25 miles ride offers more scenic views.
#cycling #summer #Germany

Load older posts