Grimoire
Overview
Grimoire is an open source, local-first bookmark manager for people who save a lot of technical links and need to find them again later. Save a URL and Grimoire stores it, extracts a readable copy of the page content and any media, and lets you organise everything with tags and categories. Keyword and full-text search runs across titles, descriptions and the extracted page text, so a bookmark you saved months ago is a few keystrokes away.
This SecureAnyCloud image runs Grimoire on Ubuntu 24.04 on Azure. Grimoire has no password login of its own, so the image keeps its daemon private and puts nginx in front of it, protected by an HTTP Basic credential that is unique to your VM. Your library stays on your own VM, and nothing leaves it until you choose to connect your own AI provider.
What you get
- Grimoire 1.0.1: the official upstream release, built from the pinned
v1.0.1tag with its React frontend compiled in. It is free and open source under the MIT license, and it is captured into the VM so your instance starts in seconds with nothing to download. - Bun runtime and SQLite: a React single-page application served by a small Bun daemon (upstream name
littleimpd) on127.0.0.1:3210. Everything persists to an embedded SQLite database, so there is no external database to run. - nginx: the single public listener on port 80, gated by a per-instance HTTP Basic credential.
- First-boot credential generation: a fresh
adminweb password, unique to each VM and written to a file that onlyrootcan read. - AI disabled by default: the optional LLM enrichment and embeddings are off, so your library is fully private until you connect your own provider.
- A bundled self-test: it creates a bookmark and reads it back through the authenticated proxy, proving the platform works end to end.
- 24/7 SecureAnyCloud support.
Grimoire is a trademark of its respective owner. This image is produced by SecureAnyCloud and is not affiliated with, endorsed by, or sponsored by the Grimoire project or Robert Goniszewski. It ships the free and open source MIT licensed software.
Prerequisites
Before you deploy, make sure you have:
- An Azure subscription with permission to create virtual machines.
- An SSH key pair for administrative access.
- A network security group that allows inbound TCP 22 (SSH) and TCP 80 (web UI) from your own address ranges.
- A VM size of
Standard_B2s(2 vCPU, 4 GB RAM) or larger.
Deploy from the Azure Portal
- Open the Azure Marketplace and search for Grimoire on Ubuntu 24.04 LTS by SecureAnyCloud.
- Select Create, then choose your subscription, resource group and region.
- Pick a VM size of
Standard_B2sor larger. - Under Administrator account, select SSH public key and supply your public key.
- Under Inbound port rules, allow SSH (22) and HTTP (80).
- Select Review + create, then Create.
Deploy from the Azure CLI
az group create --name grimoire-rg --location eastusaz vm image terms accept --urn sac1647283583153:grimoire:default:latest
az vm create \
--resource-group grimoire-rg \
--name grimoire-vm \
--image sac1647283583153:grimoire:default:latest \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku Standard
az vm open-port --resource-group grimoire-rg --name grimoire-vm --port 80 --priority 1010Connect to your VM
ssh azureuser@<vm-ip>Confirm the services are running
Three systemd units make up the deployment: grimoire (the Bun daemon), grimoire-firstboot (the one-shot unit that generates this VM's credential) and nginx (the public front door). Check that the daemon and nginx are running.
systemctl is-active grimoire nginxBoth report active. The first-boot unit runs once on the very first boot to create this VM's credential, then completes:
systemctl is-active grimoire-firstboot || echo "grimoire-firstboot: one-shot completed"The Bun daemon is lightweight and fits comfortably on a Standard_B2s. Check its memory use:
ps -o rss= -C bun | awk '{s+=$1} END{printf "grimoire daemon RSS: %d MiB\n", s/1024}'Confirm the network exposure
Grimoire is deliberately not reachable directly. Only nginx listens publicly. List the listening sockets:
ss -tln | grep -E ':(80|3210) 'The output shows 127.0.0.1:3210 for the Grimoire daemon and 0.0.0.0:80 for nginx. The daemon publishes no public port and is reachable only from nginx over the loopback interface.
Read the per instance credential
Every VM generates its own web credential on first boot and writes it to a file that only root can read. Print the file:
sudo cat /root/grimoire-credentials.txtThe file records the web credential (WEB_USER and WEB_PASSWORD) and this VM's URL (GRIMOIRE_URL). Confirm that the file is locked down:
ls -l /root/grimoire-credentials.txtstat -c '%a %U:%G %n' /root/grimoire-credentials.txtUnderstand the security model
This is the most important section of the guide, because Grimoire's design is unusual for a hosted app.
Grimoire is local-first and has no login of its own. Upstream, it is meant to run on your own machine, bound to the loopback interface, with its browser UI and API trusted for local use only. Its documentation is explicit that exposing the daemon directly on a public network is not a supported mode. On a public IP, anyone who could reach the port could read and change your whole library.
This image therefore puts a gate in front of the daemon, which is the reverse-proxy pattern upstream recommends for remote access:
- The Grimoire daemon binds to
127.0.0.1:3210and is never directly reachable. - nginx on port 80 is the only public listener. It requires HTTP Basic authentication with this VM's unique
WEB_USERandWEB_PASSWORD. - The optional AI enrichment is disabled, so no bookmark content is sent to a third party.
You can verify the gate yourself. Without a credential, and with a wrong one, the front door returns 401:
curl -s -o /dev/null -w 'no credential: HTTP %{http_code}\n' http://127.0.0.1/curl -s -o /dev/null -w 'wrong credential: HTTP %{http_code}\n' -u '<WEB_USER>:definitely-wrong' http://127.0.0.1/With the real credential it returns 200:
curl -s -o /dev/null -w 'per VM credential: HTTP %{http_code}\n' -u '<WEB_USER>:<WEB_PASSWORD>' http://127.0.0.1/The image also ships a self-test that proves the whole platform works, not merely that a page loads. It confirms that an unauthenticated request is refused. It then signs in with the per-VM credential, creates a bookmark whose URL is unique to this run, and reads that exact bookmark back:
sudo /usr/local/sbin/grimoire-roundtrip.shOpen Grimoire in your browser
Browse to your VM's URL, which is recorded in the credentials file:
<GRIMOIRE_URL>When your browser asks for the web credential, enter WEB_USER and WEB_PASSWORD from Step 6. Grimoire's library then loads. Every bookmark you save is fetched, its readable content is extracted and indexed, and it is listed with its source domain.
Save a bookmark
Select Add and paste any URL, or use the search bar as a quick-add box. Grimoire saves the link immediately and queues a background job. The job fetches the page, extracts a readable copy of the content and any media, and indexes it for search.
You can also save from the API, using the same call the browser extension makes:
curl -s -o /dev/null -w 'save bookmark: HTTP %{http_code}\n' \
-u '<WEB_USER>:<WEB_PASSWORD>' \
-H 'Content-Type: application/json' \
-d '{"url":"https://kubernetes.io/docs/concepts/"}' \
http://127.0.0.1/bookmarksSearch your library
Type in the search bar to run a keyword and full-text search across titles, descriptions and the extracted page text. Matches are highlighted. Because the whole page content is indexed, you can find a bookmark by a phrase you remember from the article, even if it is not in the title.
Select any bookmark to open its detail view. It shows the extracted readable content and any media pulled from the page, with controls to tag, categorise, archive or add notes.
Optional: enable AI enrichment with your own provider
Grimoire can summarise, auto-tag and semantically search your library using an LLM and an embedding model. This is disabled by default in this image, so nothing leaves your VM.
To enable it, open Settings → AI and choose a provider. Use either a hosted provider such as OpenAI with your own API key, or a local model server such as Ollama running on a machine you control. Then save. Until you do, keyword and full-text search work as described above.
Back up your library
Your whole library lives in a single SQLite database under /var/lib/grimoire. To take a point-in-time backup, stop the daemon briefly and copy the data directory:
sudo systemctl stop grimoire && sudo tar czf /tmp/grimoire-backup.tgz -C /var/lib grimoire && sudo systemctl start grimoire && echo backup-doneGrimoire also has a built-in backup feature under Settings → Backup. It supports scheduled snapshots and optional upload to S3-compatible storage.
Security notes
- Secure by default. The daemon is loopback-only, and the single public door is gated by this VM's unique credential. There is no shared or default password in the image.
- Restrict the network. Allow inbound TCP 80 only from address ranges you trust. Put the VM behind TLS before you expose it to the public internet, for example with an Azure Application Gateway or with nginx and your own certificate.
- Rotate the web credential at any time. Edit
/etc/grimoire/htpasswdwithopenssl passwd -apr1, then reload nginx. - Keep the OS patched. The image is patched at build time and ships with unattended security upgrades enabled.
Support
SecureAnyCloud produces and supports this image. For help with your deployment, contact SecureAnyCloud support. Grimoire itself is developed by the upstream open source project.
Deploy on Azure
Launch Grimoire on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com