2025-11-11
It's been exactly 5 years since Perkeep's last release.
That's a long time between releases, sorry! I guess I got distracted at my new job (Tailscale) (and kids). Tailscale's based out of Toronto and while I've never been there, it seems like a good enough city name for a release.
A highlight of this release is built-in Tailscale support, using Tailscale's tsnet (Tailscale-as-a-library). So you don't need a public server to run your perkeepd server. Instead, it can just be a peer in your tailnet, and using Tailscale for the authentication as well.
Downloads
Container images (new) are at https://github.com/perkeep/perkeep/pkgs/container/perkeep
macOS (darwin) builds aren't included in this release, as we haven't set up macOS signing+notarization yet (#1737).
Changes
Other merged work since v0.11 follows, as compiled by @radkat:
Core & Infrastructure
Go Modernization
- Upgraded Go version: 1.15 → 1.16 → 1.19 → 1.21 → 1.25 (@bradfitz, @radkat)
- Replaced legacy io/ioutil with io and os (@alexandear)
- Removed +build tags in favor of //go:build (@bradfitz)
- Removed legacy AppEngine, GCE deploy, and GopherJS publisher support (@bradfitz)
- Adopted go:embed for asset embedding (@bradfitz, @aviau)
- Migrated Perkeep website hosting to Fly.io (@bradfitz)
- Cleaned up obsolete setup wizard and make system (@bradfitz, @psanford, @veggiemonk)
Dependencies & Build
- Updated dependencies across the project (@tgulacsi, @radkat)
- Adopted modern replacements: modernc.org/sqlite, modernc.org/kv, etc.
- Improved Docker builds: smaller, faster, Go module–based (@willnorris, @MichaHoffmann)
- Added ca-certificates to importers to fix network access issues (@tevino)
CI / Tests / Lint
- CI extended to macOS and Windows (@aviau, @willnorris)
- Introduced strict vet/lint/staticcheck passes (@aviau, @bradfitz)
- Unified test helpers using T.TempDir, T.Setenv, and T.Cleanup (@Juneezee, @alexandear, @bradfitz)
- Race detection enabled in devcam (@MichaHoffmann)
- Resolved linter errors across multiple packages (@radkat)
- Integration tests now run outside GOPATH with GOMOD awareness (@veggiemonk)
Storage, Encryption & Indexing
Encryption
- Migrated to age encryption (@MichaHoffmann)
- Added fingerprint support in pk-put and perkeepd configs (@aviau)
- Added permission checks for key files (@aviau)
- Verified permanode signatures, not just claims (@aviau)
- Fixed encryption race conditions and improved armored keyring handling (@MichaHoffmann, @featherbutt, @aviau)
Storage
- Cleaned up and unified diskpacked, blobpacked, and blobserver backends (@tgulacsi, @bradfitz)
- Documented B2, S3, and GCS configuration, with unified examples (@aviau, @mccurdyc, @MichaHoffmann)
- Migrated B2 backend to AWS SDK (@kalidor)
- Added far-future caching headers for blob responses (@surma)
- Prevented IO errors on missing blobrefs (@aviau)
- Optimized S3 query performance on startup (@lologarithm)
Indexing
- Improved index consistency using sorted.KeyValue (@aviau)
- Verified signatures on permanodes and added tests for out-of-order indexing (@MichaHoffmann)
- Removed deprecated SQL index (@zenhack)
- Added untagged search predicate (@alextsui05)
Web UI & Frontend
Migration to JS
- Full migration from goui → modern JS, including:
- downloadbutton, aboutdialog, SelectAllBtn, ImportShare, DirChildren, ShareItem, mapquery, etc. (@aviau)
- Deprecated old goui build system (@aviau)
- Cleaned up and reorganized index.js for frontend routing (@aviau)
- Removed obsolete UI code (@MichaHoffmann)
- Removed red “experimental” banner in Tailscale mode (@radkat)
Frontend Enhancements
- Updated map.js to use tile.osm.org (@Firefishy)
- Added OpenStreetMap geocoding API (@willnorris)
- Added curl API query examples (@ginabythebay)
- Removed outdated publisher and GopherJS support (@bradfitz)
Server, Network , Tailscale
- Added Tailscale tsnet integration to auth, webserver, serverinit (@bradfitz)
- Removed deprecated network subsystems (CamliNetIP, camnetdns, gpgchallenge) (@bradfitz)
- Improved HTTP utilities to support 8 MB+ responses (@bobg)
- Fixed HTTP timezone headers (@zhangzqs)
- Fixed server panics on missing modtime or time metadata (@MichaHoffmann)
- Allowed importers to skip paid API calls (@radkat)
Filesystem & FUSE
- Dropped macOS FUSE support (@bradfitz)
- Fixed panics and file truncation bugs in FUSE (@MichaHoffmann)
- Improved cache isolation in tests (@MichaHoffmann)
- Prevented IO errors on missing blobs (@aviau)
Schema, Importers & GC
- Introduced CamliType type for schema clarity (@aviau)
- Simplified schema parsing logic (@bradfitz)
- Fixed linter issues in importer packages (@radkat)
- Added option to skip paid API calls in importers (@radkat)
- Fixed GC package linter issues (@radkat)
- Added comprehensive documentation of environment variables (@aviau)
Documentation, Examples & Misc
- Documented all environment variables and new storage configs (@aviau, @mccurdyc)
- Standardized schema blob size to ≤ 1 MB (@aviau)
- Added B2 and cloud storage permission examples (@aviau)
- Fixed typos and docs cleanup (@luzpaz, @fetsorn)
- Added curl query demo (@ginabythebay)
- Removed unused code and deprecated assertions (@tgulacsi, @MichaHoffmann)
Bug Fixes
- Fixed incorrect fmt.Errorf usage, slice init length, and file closing bugs (@alingse, @cuishuang, @testwill)
- Fixed image decoding crash (@MichaHoffmann)
- Fixed encryption race condition and various small panics (@MichaHoffmann)
- Fixed timezone and HTTP header inconsistencies (@zhangzqs)
Highlights Summary
| Language & Build | Migrated to Go 1.25, replaced legacy systems, modernized embedding |
| UI | Complete migration from GopherJS/goui → native JS |
| Encryption | Adopted age, added fingerprint + armored keyring support |
| Storage | Unified S3/B2/GCS docs and configs; improved caching |
| Networking | Tailscale tsnet integration, improved HTTP utilities |
| Testing | Added race detection, staticcheck cleanup, CI on macOS/Windows |
| Docs | Refreshed 0.11 release, added modern examples and schema guidelines |
New Contributors
Huge thanks to all new contributors who made their first commits in this release!
- @aviau made their first contribution in #1345
- @psanford made their first contribution in #1270
- @lologarithm made their first contribution in #1386
- @bobg made their first contribution in #1295
- @tgulacsi made their first contribution in #1394
- @alextsui05 made their first contribution in #1393
- @jincheng9 made their first contribution in #1574
- @tevino made their first contribution in #1578
- @fetsorn made their first contribution in #1580
- @MichaHoffmann made their first contribution in #1585
- @Juneezee made their first contribution in #1586
- @surma made their first contribution in #1571
- @luzpaz made their first contribution in #1604
- @featherbutt made their first contribution in #1612
- @kalidor made their first contribution in #1599
- @sbinet made their first contribution in #1611
- @mccurdyc made their first contribution in #1621
- @ginabythebay made their first contribution in #1634
- @bradfitz made their first contribution in #1642
- @alexandear made their first contribution in #1647
- @Firefishy made their first contribution in #1659
- @veggiemonk made their first contribution in #1677
- @testwill made their first contribution in #1687
- @cuishuang made their first contribution in #1689
- @zhangzqs made their first contribution in #1685
- @alingse made their first contribution in #1692
- @dependabot[bot] made their first contribution in #1712
.png)


