# Shaarli: a single-user bookmark service that runs on PHP and flat files

> Shaarli stores bookmarks in files instead of a database and ships as a PHP application with a Docker image. It suits one person or a small group who wants to own their link archive, not a team building a shared knowledge base.

**shaarli/Shaarli** — The personal, minimalist, super-fast, database free, bookmarking service - community repo

- Repository: https://github.com/shaarli/Shaarli
- Website: https://shaarli.readthedocs.io/
- Stars: 3,903 · Forks: 315
- Language: PHP
- License: NOASSERTION
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/shaarli-shaarli

## What Shaarli is for, and who it is not for

Shaarli describes itself as "personal (single-user), fast and handy" and as a link sharing service you install on your own server. That single-user framing is the whole design premise. There is no organisation model, no per-user permission table and no shared workspace: the instance belongs to one person who saves links and optionally publishes them.

The problem it solves is narrow and real. Public bookmark services can change their terms, shut down or start charging, and a link archive is the kind of data that is annoying to lose. Shaarli keeps the archive on hardware you control, with no database process to run. The README's own tagline calls it "database free", which is the constraint that shapes everything else in the repository.

Where it is the wrong tool: a team that wants shared tags, comment threads and per-member accounts will spend more time working around the single-user model than the tool saves. The same applies to anyone who wants a managed service with no server to patch.

## How the database-free storage model actually works

The repository layout tells most of the story. There is no migrations directory and no schema file. Instead there are data/, cache/, pagecache/ and tmp/ at the top level, alongside application/, inc/, tpl/ and plugins/. Links and their metadata live in those directories as files, and the application reads and writes them directly through PHP.

That choice has consequences you can see in the Docker setup. The Dockerfile copies the application into /var/www/shaarli and then runs chown -R nginx:nginx on it, because the web process needs write access to the data directories. The docker-compose.yml declares two named volumes, shaarli-cache and shaarli-data, mounted at /var/www/shaarli/cache and /var/www/shaarli/data. Those two mounts are your archive. If they are not backed up, the bookmarks are not backed up.

The build itself is a four-stage Dockerfile: a Python Alpine stage runs make htmldoc to build the documentation, a Composer stage installs PHP dependencies with composer --prefer-dist --no-dev install, a Node 22 Alpine stage enables corepack, prepares yarn@4.1.0 and runs yarnpkg run build, and the final Alpine stage installs php84 with a specific extension list (ctype, curl, gd, gettext, iconv, intl, json, ldap, mbstring, openssl, session, xml, simplexml, zlib) plus nginx and s6. That extension list is effectively the runtime requirement sheet for a manual install.

## Installing Shaarli with Docker Compose

The repository ships a docker-compose.yml that pairs the Shaarli image with Traefik 1.7 as a TLS-terminating reverse proxy. It reads three environment variables: SHAARLI_VIRTUAL_HOST for the fully qualified domain name, SHAARLI_LETSENCRYPT_EMAIL for certificate renewal, and SHAARLI_DOCKER_TAG for the image tag. The image reference is ghcr.io/shaarli/shaarli:${SHAARLI_DOCKER_TAG}, and the compose file also keeps a build: ./ entry so you can build from the checkout instead.

Start the stack from the repository root:

```bash
docker compose up -d
```

Traefik binds ports 80 and 443 and requests a certificate for the host you named in SHAARLI_VIRTUAL_HOST. Expect the first request to redirect from HTTP to HTTPS, and give the ACME challenge a moment to complete before assuming something is broken.

The two volumes declared in the compose file are what you must preserve:

```yaml
volumes:
  - shaarli-cache:/var/www/shaarli/cache
  - shaarli-data:/var/www/shaarli/data
```

If you would rather not run Traefik, the compose file is a template: the shaarli service only needs the two volume mounts and a network, and you can put your own proxy in front of it. The README points to https://shaarli.readthedocs.io for the full documentation, and the repository also offers a public demo at https://demo.shaarli.org with the login demo and password demo, which is the cheapest way to see the interface before you commit to a server.

## The limits you should weigh before adopting it

The single-user design is a limit, not a setting. The README states it plainly, and nothing in the repository layout suggests an account or role system that would change that. If several people need to contribute links, they share one login or they do not contribute.

Flat-file storage is the second limit. It is what makes the install database-free and easy to move, but it also means the data directories are the application's working state, not a read-only export. The Docker image grants the nginx user ownership of the whole application tree so it can write there. A backup that copies only the code and forgets shaarli-data gets you a working instance with no bookmarks in it.

The README does not document any rollback procedure, and the changelog is a separate file rather than something the README summarises. Before upgrading across releases, read CHANGELOG.md and take a copy of the data volume first. The repository also carries SECURITY.md, which is where the project says to look for its security policy; the README itself gives no disclosure process.

Finally, the licence field is NOASSERTION, and package.json points to "SEE LICENSE IN COPYING". That means the per-component terms are spelled out in the COPYING file rather than in a single SPDX identifier. If you plan to redistribute Shaarli, read COPYING before you do.

## Shaarli compared with a database-backed bookmark manager

The obvious alternative is a bookmark manager built on a relational database, where links, tags and users are rows and the application queries them. That approach buys you multi-user accounts, transactional writes and a query interface other tools can use. It also buys you a database process to install, back up, migrate and keep running.

Shaarli takes the opposite position on every one of those points. No database means no separate service to monitor and no connection string to configure; the trade is that concurrent writes and complex queries are not what the storage layer is built for. A database-backed manager can hand you a stable schema to report on; Shaarli hands you a directory tree to copy.

Which one is right depends on the shape of the archive. One person curating links over years, on a small VPS, with backups they understand: Shaarli's model is simpler to reason about. Several people contributing to a shared, queryable catalogue: the database-backed design is doing work Shaarli deliberately does not do. The Docker Compose example makes the deployment trade-off visible too, since it bundles a reverse proxy and certificate automation rather than assuming a platform will handle TLS for you.

## Maintenance, upgrades and licence questions

The repository is not archived, and the last push was on 2026-09-04. Recent releases are v0.16.5 on 2026-07-31, v0.16.4 on 2026-07-31 and v0.16.3 on 2026-05-28, so the release cadence in the period covered by the changelog is a patch release roughly every few weeks to a couple of months.

Upgrading a Docker deployment means pulling a new SHAARLI_DOCKER_TAG and recreating the container. The data lives in the named volumes, so the container itself is disposable, which is the main maintenance advantage of the image-based install. A manual install carries more: the Dockerfile's php84 extension list is the practical checklist, and composer install plus the frontend build (corepack prepare yarn@4.1.0 --activate, yarnpkg install, yarnpkg run build) are steps the image does for you. The repository also has a Makefile with a docker_% target that rsyncs the sources into a user-owned directory so tests can run as a non-root user, which is a hint that the maintainers expect contributors to work inside a container.

On licensing, the repository does not carry a single declared licence identifier. COPYING is described as covering the contributors and the licences of each individual component, and package.json says "SEE LICENSE IN COPYING". Treat COPYING as the authoritative document and read it rather than assuming a licence from the repository metadata.

## Conclusion

Adopt Shaarli if you are one person (or a small trusted group) who wants a link archive on your own server and is comfortable managing a PHP application, its data/ and cache/ directories and its backups. Do not adopt it if you need multi-tenant accounts, a hosted service with no maintenance, or a bookmark store that must be queried by other applications through a documented API. Before committing, verify three things on your own instance: that the PHP extensions listed in the Dockerfile are present on your host, that your backup routine actually captures the data/ and cache/ volumes, and that the licence terms in COPYING match how you intend to redistribute the code.

## FAQ

### What is Shaarli?

Shaarli is a self-hosted, single-user bookmarking service written in PHP. The README describes it as personal, minimalist, fast and database free, and it is designed to run on your own server.

### How do I install Shaarli with Docker?

The repository includes a docker-compose.yml that uses the image ghcr.io/shaarli/shaarli:${SHAARLI_DOCKER_TAG} alongside Traefik. You set SHAARLI_VIRTUAL_HOST, SHAARLI_LETSENCRYPT_EMAIL and SHAARLI_DOCKER_TAG, then start the stack with docker compose up -d.

### Does Shaarli need a database?

No. The README calls it database free, and the repository stores state in directories such as data/, cache/, pagecache/ and tmp/ rather than in a database schema. In the Docker setup, the shaarli-data and shaarli-cache volumes are the parts you need to back up.

## Sources

- [Issues](https://github.com/shaarli/Shaarli/issues)
- [Project website](https://shaarli.readthedocs.io/)
- [README](https://github.com/shaarli/Shaarli/blob/master/README.md)
- [Releases](https://github.com/shaarli/Shaarli/releases)
- [shaarli/Shaarli on GitHub](https://github.com/shaarli/Shaarli)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/shaarli-shaarli
