The script installs and exposes the database only; it now prints a generic MongoDB connection string (mongodb://user:pass@ip:27017/) instead of a LibreChat MONGO_URI with a hardcoded /LibreChat database. README 'Wiring LibreChat' section replaced with a generic 'Connecting a client' section. Application wiring is left to that app's own config or a separate script.
9.5 KiB
FerretDB
Automated installation and update script for FerretDB — a truly open-source, MongoDB-compatible database — running inside a Debian LXC on Proxmox.
A drop-in MongoDB replacement for any app that speaks the MongoDB wire protocol (e.g. LibreChat) without running MongoDB itself. The script installs and exposes the database only; wiring it into an application is left to that app's own configuration (a separate script, or manually).
Why Debian and not Alpine?
FerretDB v2 is two pieces:
- the FerretDB proxy (a static Go binary), and
- PostgreSQL + Microsoft's DocumentDB extension, the mandatory storage engine.
The DocumentDB extension is a compiled C PostgreSQL extension and is published only as
deb/rpm packages (deb11, deb12, ubuntu, rhel) — there is no Alpine/musl build.
So, unlike the openbao/gitea-runner Alpine LXCs in this repo, this stack runs on Debian 12
(deb12, the newest target the extension ships for).
Features
Single script, automatic mode selection:
| Context | Action |
|---|---|
| From Proxmox host, no existing FerretDB container | Detects newest Debian template, creates LXC, installs PostgreSQL + DocumentDB + FerretDB |
| From Proxmox host, FerretDB container already present | Reuses the existing LXC, refreshes packages, upgrades the FerretDB stack to latest |
From inside an LXC, no ferretdb binary |
Installs the full stack from scratch |
From inside an LXC, ferretdb already present |
Updates the packages only (no config / role / data changes) |
The container is identified by hostname and the ferretdb tag, so it is re-found across
reruns even if the CTID was auto-allocated the first time.
Requirements
- Proxmox VE host with
pveam,pct,pvesh,jqavailable - Internet access from both the host (template download) and the LXC (package downloads)
- Script must be run as root on the Proxmox host (enforced; the Web UI shell qualifies)
Usage
Full install (from Proxmox shell)
bash -c "$(curl -fsSL https://gitea.arnodo.fr/Damien/infra-scripts/raw/branch/main/ferretdb/install.sh)"
The script prints the generated password and the ready-to-paste MONGO_URI at the end.
Save them — the password is not persisted on the Proxmox host.
Re-running the exact same command later upgrades packages inside the LXC and brings the FerretDB stack to the latest release, without touching the config, role, or PostgreSQL data.
Customisation
Every parameter is exposed as an environment variable:
| Variable | Default | Description |
|---|---|---|
CTID |
auto | Container ID (auto-allocated via pvesh get /cluster/nextid) |
FERRETDB_HOSTNAME |
ferretdb |
LXC hostname |
TEMPLATE |
auto-detected | Debian template; auto-detected from pveam available |
STORAGE |
local-lvm |
Proxmox storage for the LXC root disk |
TEMPLATE_STORAGE |
local |
Storage where Debian templates live |
CORES |
2 |
vCPU cores |
RAM |
2048 |
RAM in MiB (Postgres + FerretDB) |
DISK |
16 |
Root disk size in GB |
BRIDGE |
vmbr0 |
Network bridge |
LXC_TAG |
ferretdb |
Stable tag used to re-discover the container |
PG_VERSION |
17 |
PostgreSQL major version (from PGDG) |
DOCUMENTDB_TAG |
latest |
DocumentDB release tag (couples documentdb + FerretDB versions); pin e.g. v0.107.0-ferretdb-2.7.0 |
DOCUMENTDB_DISTRO |
deb12 |
Distro target in the documentdb deb filename. Escape hatch for a future deb13 (set with TEMPLATE) |
FERRETDB_LISTEN_ADDR |
0.0.0.0:27017 |
TCP listener. Exposed on all interfaces — it is a database other hosts must reach. |
FERRETDB_USER |
ferretdb |
App user — both the PostgreSQL role and the MongoDB user clients authenticate as |
FERRETDB_PASSWORD |
auto-generated | Auto-generated (openssl rand -hex 24) when unset; printed in the final summary |
TS_AUTHKEY |
(unset) | Pre-auth key (generate at https://login.tailscale.com/admin/settings/keys). If unset, finish tailscale up manually inside the LXC. |
CTID=220 FERRETDB_HOSTNAME=mongo RAM=4096 DISK=32 \
bash -c "$(curl -fsSL https://gitea.arnodo.fr/Damien/infra-scripts/raw/branch/main/ferretdb/install.sh)"
Connecting a client
Any MongoDB driver or tool connects with a standard connection string (the script prints the exact one, with the generated password, at the end of the install):
mongodb://ferretdb:<password>@<lxc-ip-or-tailnet-fqdn>:27017/
Append a database name to target one (e.g. …:27017/myapp); it is created on first write.
Wiring this into a specific application (setting its Mongo connection string, disabling any
bundled MongoDB it ships, etc.) is intentionally out of scope — do it from that app's own
config or a dedicated script.
Tailscale
The LXC joins the tailnet (tailscale up --ssh) so a client on another node can reach the
database over the tailnet. Unlike the openbao script there is no tailscale serve — the
MongoDB wire protocol is raw TCP, not HTTP, so the listener is exposed directly on
0.0.0.0:27017 (LAN + tailnet) by design.
If TS_AUTHKEY was supplied the node is brought up automatically; otherwise finish it
manually inside the LXC:
pct enter <CTID>
tailscale up --ssh --hostname ferretdb
tailscale status # prints the tailnet FQDN
Because the listener is on
0.0.0.0, restrict access with your tailnet ACLs and/or a host firewall — anyone who can route to TCP 27017 can attempt to authenticate.
Update (from inside the LXC)
curl -fsSL https://gitea.arnodo.fr/Damien/infra-scripts/raw/branch/main/ferretdb/install.sh | bash
The script auto-detects the presence of /usr/bin/ferretdb and switches to update mode:
packages are upgraded (including the DocumentDB extension via
ALTER EXTENSION documentdb UPDATE) and the services are restarted. The config, the
PostgreSQL role, and the data are left untouched.
Architecture
- OS: latest Debian LXC template (auto-detected), unprivileged,
nesting=1,/dev/net/tunpassthrough for Tailscale - Storage engine: PostgreSQL
17(PGDG) + the DocumentDB extension (pg_documentdb,pg_cron), loopback-only on127.0.0.1:5432 - Proxy: official
ferretdbdeb fromgithub.com/FerretDB/FerretDB, systemd unit, listening on0.0.0.0:27017 - Auth: the app user is provisioned through
documentdb_api.create_user(rolesclusterAdmin+readWriteAnyDatabase), not a plainCREATE ROLE. DocumentDB builds the SCRAM-SHA-256 verifier with its own 28-byte salt (documentdb.scramDefaultSaltLen); a native PostgreSQL role would store a 16-byte salt that MongoDB clients reject (invalid salt length of 16 in sasl step2). FerretDB connects to PostgreSQL as the same user. - Network: FerretDB exposed on
0.0.0.0:27017; Tailscale runs in the LXC for tailnet reachability (noserve) - Config:
/etc/postgresql/17/main/conf.d/documentdb.conf(extension settings) and/etc/systemd/system/ferretdb.service.d/override.conf(FERRETDB_POSTGRESQL_URL,FERRETDB_LISTEN_ADDR) - Logs: PostgreSQL via its stock
logrotate; FerretDB via journald, capped atSystemMaxUse=200M - Version tracking:
/opt/ferretdb_version.txtrecords the installed DocumentDB tag for idempotent reruns