Deployment
For initial setup see Getting Started. This page covers production-specific concerns.
How the Docker Setup Works
The frontend container runs nginx, which both serves the React SPA and proxies all /api/, /carddav/, and /.well-known/carddav requests to the backend container. The backend is not port-mapped to the host — it is only reachable within the Docker network. Leave REACT_APP_API_URL empty in .env.docker to use this built-in proxy.
You only need an external reverse proxy for TLS termination. Point it at the frontend container port (default 7300):
server {
listen 443 ssl;
server_name meerkat.example.com;
location / {
proxy_pass http://localhost:7300;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
}
}
Production Environment
Set these variables in .env.docker when running over HTTPS:
| Variable | Value |
|---|---|
FRONTEND_URL | Exact origin, e.g. https://meerkat.example.com (never *) |
COOKIE_SECURE | true |
COOKIE_DOMAIN | Your domain |
JWT_SECRET_KEY | Generate with openssl rand -base64 32 |
File Permissions
The backend container runs as group 1001. Host directories for data and photos must be writable:
chown -R :1001 /path/to/data /path/to/photos
chmod -R 775 /path/to/data /path/to/photos
Upgrades
docker compose pull
docker compose up -d
Database migrations run automatically on startup.
Backups
Back up the SQLite database file and photo directory:
cp /path/to/data/meerkat.db /backups/meerkat-$(date +%F).db
rsync -a /path/to/photos/ /backups/photos/
The database can be copied while the app is running (SQLite WAL mode).
FAQ
- The backend seems to start correctly but then nothing works Have a look at the docker logs, a likely issue could be that the database and photo folders are readonly for the docker user. Use
chown -R 1001:1001 ./data ./photosto fix this (change the relative paths to the paths on your filesystem).