Install
Tastebase runs as one Docker container. The image works on linux/amd64 and linux/arm64, so a NAS, a Raspberry Pi 4 or 5, or any Linux server will do. You need Docker with Compose.
-
Get the Compose file and the settings template.
mkdir tastebase && cd tastebase curl -O https://raw.githubusercontent.com/ReeceRose/tastebase/main/docker-compose.yml curl -o .env https://raw.githubusercontent.com/ReeceRose/tastebase/main/.env.docker.example -
Make two secrets. Run this twice and paste one result into
BETTER_AUTH_SECRETand the other intoENCRYPTION_SECRETin.env. They must be different.openssl rand -base64 48 -
Set
BETTER_AUTH_URLin.envto the address people will type, such ashttp://192.168.1.100:3000. It has to match what's in the browser, including the port, or sign-in won't work. -
Start it.
docker compose up -d -
Open your
BETTER_AUTH_URLand create the first account.
Recipes live in the tastebase-data volume and photos in tastebase-uploads, so both survive restarts and upgrades.
Using Unraid? There's a separate Unraid guide. For docker run and host folders, see the deployment guide.
Set up the house
Everyone else opens the same address and picks Create an account. There are no invitations to send.
While sign-ups are open, anyone who can reach your Tastebase can create an account and see recipes shared with the house. Close them once everyone's in.
Close sign-ups
Add this to .env, then apply it. Bring it back to true whenever someone new joins.
echo "ALLOW_SIGN_UPS=false" >> .env
docker compose up -d
Who sees what
Each recipe is either Shared with the house or Only you. Notes work the same way: leave one for everyone, or keep it to yourself.
Forgotten passwords
Tastebase doesn't send email. When someone asks for a password reset, the link is written to the server log, and whoever runs the server can pass it on.
docker compose logs tastebase | grep resetLink
Add recipes
Start from Add a recipe. Every import opens in the editor, so you can check it before saving.
Link, text or photo
- Link: reads the recipe data from most sites, then falls back to the page text. The recipe's photo becomes the main photo, and you can pick from the page's other photos.
- Text: paste a recipe and it's split into ingredients and steps.
- Photo: take a picture of a cookbook page. It's read on your server.
The browser extension
Save to Tastebase brings in the page you're looking at. It works on sites that block link imports, like Serious Eats and Allrecipes, and on subscriber sites you're signed in to, like NYT Cooking. It works in Chrome, Edge, Brave and Arc, and sends nothing anywhere except your own Tastebase.
Download the Tastebase source and unzip it.
Open
chrome://extensionsand turn on Developer mode.Click Load unpacked and choose the
extensions/chromefolder.On the setup page that opens, enter your Tastebase address and allow access when asked.
Pin the extension. On any recipe, click its icon or press Alt+Shift+T, then Save to Tastebase.
From your phone
The steps are in Tastebase under Settings, Saving recipes, with your address already filled in.
- Android: install Tastebase from Chrome's menu with Add to home screen, then share any recipe link to it. Android only installs from an
httpsaddress, so you'll need one of the options below. - iPhone and iPad: iOS doesn't let web apps join the share sheet, so you set up a Shortcut once.
On a phone, Tastebase reads the recipe from the link itself. A few sites block that. For those, copy the recipe text and paste it into Add a recipe.
Cook
Open a recipe and choose Start cooking. Cook mode shows one step at a time, full screen, with timers and ingredient tick-offs, and keeps the screen on.
On the recipe page, change the servings to scale the amounts, or switch between metric and imperial. Your default units are in Settings, Units.
Update and back up
Update
Database changes apply on their own when the new container starts. Back up first.
docker compose pull
docker compose up -d
latest always points at the newest release. To choose when you upgrade, pin a version in docker-compose.yml, such as ghcr.io/reecerose/tastebase:0.1.1. What's changed is listed on the Releases page.
Back up
This stops Tastebase so the database is consistent, then writes one archive of your recipes and photos to the current folder.
docker compose stop
docker run --rm --volumes-from tastebase -v "$PWD":/backup alpine \
tar czf /backup/tastebase-$(date +%Y%m%d).tar.gz -C /app data uploads
docker compose start
Restore
This replaces what's there now. Change the filename to your backup's.
docker compose stop
docker run --rm --volumes-from tastebase -v "$PWD":/backup alpine \
sh -c "cd /app && tar xzf /backup/tastebase-20261107.tar.gz"
docker compose start
Reach it from outside
Don't expose port 3000 directly to the internet. To use Tastebase away from home, or to get the https address Android needs, pick one of these and set BETTER_AUTH_URL to the new address. If it can be reached from the internet, close sign-ups first.
- A private network: Tailscale gives you a secure address only your devices can reach.
- A Cloudflare Tunnel: needs no open ports.
- A reverse proxy: serves Tastebase on your own domain.
With Caddy, this is all it takes, and it handles the certificate for you:
recipes.example.com {
reverse_proxy localhost:3000
}
With Nginx, set client_max_body_size 10m;, because photo uploads go up to 10 MB and Nginx stops at 1 MB by default. The deployment guide has full Nginx and Traefik examples.
Troubleshooting
Start with the log. It usually names the problem.
docker compose logs tastebase
Sign-in loops back to the sign-in page
BETTER_AUTH_URL doesn't match the address in the browser. Check the scheme, host and port.
The log says "Invalid environment variables"
It names the variable, and it's usually ENCRYPTION_SECRET. Generate it again with openssl rand -base64 48, which has the mix of characters it requires.
The log says "unable to open database file"
The data folder isn't writable. If you mounted host folders, run sudo chown -R 1001:1001 on them, because the container runs as uid 1001.
The port is already in use
Change the left side of ports: in docker-compose.yml, for example "8080:3000", and update BETTER_AUTH_URL to match.
It won't start after an update
The container won't start if a database change fails. Restore your last backup and open an issue with the log.
Checking that it's healthy
Run curl http://localhost:3000/api/health. It returns "status":"ok", or a 503 if the database can't be reached.