install / overview

Installation Guide

freezr is much more fun with AI

If you are trying out freezr, please do give it access to ChatGPT or Claude. It's just so much more interesting when it has LLMs running. Once you've installed freezr, head to /accounts/resources to enter your API key.

installation options

How do you want to run freezr?

Quick start

Try it on freezr.info

The fastest way to try freezr is to sign up for a trial on this server, but remember that the point of freezr is to NOT have you stay here, but to go off and create your own server.

So, you will get limited storage here - 2MB - just enough to give you a taste. (and I cant afford to pay for everyone's storage.)

Get started here
If you know node.js

Run it locally

You dont have to be a developer to run freezr on your laptop, but you need to be able to install node.js and run it on localhost.

Download freezr from github, npm install it and run npm run dev. (Best to choose local file storage and NeDB as a database.)

View on GitHub →
Bring your own keys

Connect your own storage

Whether you run on this site or any where else, you can plug in your own storage and database, and store your data in your own space, using the freezr adapters. It's your data and you do what you want with it.

If you have an S3 account for example, try registering here with a key, and choose NeDb as a database.

More on Adapters ↓
Full control

Your own server

Ideally you should have your own freezr server running on the cloud provider you choose, and the domain name you want, all fully under your control.

freezr is about data freedom - you should have full portability of your data and your apps.

Cloud Installation ↓
install / setup & settings / first-user registration

Setup / Settings

Once freezr is running it is configured in three places: a one-time first setup flow that creates the admin account, an Admin settings area for server-wide policy, and an Account settings area that each user has for their own data and credentials.

First-user registration

When a freezr server boots for the very first time, there is no admin account. The very first HTTP visitor becomes the server's admin by completing a one-time first setup flow. This flow is the same on a laptop running on localhost and on a freshly deployed cloud instance.

Once the server is running, you will be redirected to /register/firstSetUp and be asked to:

  1. Pick a user id and password for the admin account.
  2. Choose the file-system and database adapters this server will use by default (see the adapters below). On localhost this can simply be local + nedb, which needs no further credentials.
  3. On a cloud / public server only: paste the one-time setup token (FREEZR_SETUP_TOKEN) that you set when deploying. On a laptop running with NODE_ENV=development the token is skipped entirely. See the Cloud Servers section for details and the token format.

Submitting the form runs server-side checks on your chosen file system and database and marks the server as set up. The server will not accept first-setup again afterwards.

Admin settings

Available to the admin user at /admin/home. This is where server-wide policy lives — user accounts, system preferences, and advanced server functions.

FunctionNotes
List usersSee every account on the server, their file system and database types and their storage use
Manage usersEdit, suspend, or remove existing user accounts - or install apps for them.
Register a new userCreate new users on the server (bypassing the public self-register flow.)
System preferencesServer-wide policy: whether users can self-register, default FS/DB, messaging rules, etc.
Cache preferencesTune the in-memory caches to speed up cloud database access.
Review visit logsInspect the server's access logs.
Add a local microserviceRegister a locally-running microservice (e.g. a Lambda-style function) for apps to call - this is dangerous!!
Set up as OAuth serverMake this freezr instance an OAuth identity provider for other sites.
Create cloud setup tokenGenerate a fresh FREEZR_SETUP_TOKEN for bootstrapping another cloud server. See below.

Account settings

Available to every user at /account/settings. This is where a user controls their own storage, credentials, and identity on the server.

AreaFunctionNotes
System configurationShows which FS, DB, and compute adapters the account is using, with links to edit parameters.
Intelligence (LLMs)Link to /account/resources to manage Claude / ChatGPT API keys.
Resource usagePer-app storage breakdown for the user.
LogsPer-user visit / access logs and errors.
Profile pictureUpload / replace / delete the account's public profile image - used when you post publicly.
Sharing / messagingBlock sending messages to non-contacts on other servers; block receiving messages from non-contacts.
Change passwordStandard old-password + new-password flow.
Remove accountPermanently deletes the user's credentials and all their data on this server.
Advanced settings/account/reset — low-level account reset, for emergency use.
install / cloud servers

Cloud Servers

freezr is a plain Node.js app so it can be installed anywhere that runs Node: a laptop, AWS (EC2, or Elastic Beanstalk), Azure App Service, or the likes of Heroku and Replit. There is no build step and few dependencies - any Node 18+ environment works out of the box.

On a laptop you typically run npm run dev and that's it. On a public host the only thing that differs is that you set a few environment variables — most importantly NODE_ENV, a first-setup token, a credential-encryption passphrase, and the connection details for whatever file system and database you plan to use. All of that is covered below.

Environment variables

freezr reads a small set of process.env variables at startup to decide which adapters and ports to use, and to encrypt credentials at rest. On a laptop you almost never need to set any of them (unless you want to test a cloud db or fs) — the defaults (local file system, NeDB, port 3000) just work. On a cloud host (AWS, Azure, etc.) you set them in whatever "Environment variables" / "Config vars" panel the provider gives you. See below for details.

Core server

VariableDefaultNotes
PORT 3000 HTTP port the server listens on. Most PaaS providers set this for you.
NODE_ENV (unset) Set to development on a laptop to skip the first-setup token check and enable verbose logging. Leave unset (or production) on a cloud host. See NODE_ENV.
FREEZR_SETUP_TOKEN (required on cloud) One-time token authorising the first-user registration. See Set Up Token.

The specific variables for each adapter (file system, database) are listed under the adapter that uses them in the Resource adapters section below.

NODE_ENV

NODE_ENV controls the two modes freezr runs in:

  • development — used by npm run dev. Skips the first-setup token check (so you can just visit /register/firstSetUp on a laptop and become the admin), enables verbose logging, and relaxes a few other safety checks. Only appropriate on localhost.
  • production (or unset) — used by npm start and by every PaaS host. The first-setup flow refuses to run unless the caller presents a valid FREEZR_SETUP_TOKEN, preventing a random visitor from claiming the admin account before you do. Most cloud providers set NODE_ENV=production for you automatically.

Set Up Token — FREEZR_SETUP_TOKEN

The FREEZR_SETUP_TOKEN used by the cloud first-setup flow has the format <secret>.<YYYY-MM-DD> — a random 24-byte hex secret followed by an ISO expiry date (default 1 day out). After that date the token is refused with auth-setupTokenExpired. Generate one with createSetupToken() (or from the admin UI at /admin/createCloudToken). Tokens are compared with a constant-time timingSafeEqual. Typical workflow: deploy with the variable set, finish the form, and leave it be — the server will not accept first-setup again regardless, but it will require a value in the variable if / when the server restarts.

Credential encryption — FREEZR_ENV_KEY

freezr stores the FS, DB, and LLM credentials it needs at startup inside freezr_environment.js and in the info.freezr.admin.params DB record. If you set FREEZR_ENV_KEY, those credential blobs are transparently encrypted with AES-256-GCM before being written and decrypted on read, so that anyone who gets hold of the file / DB record cannot read your Dropbox tokens, S3 keys, Mongo connection strings, or LLM API keys.

VariableDetails
FREEZR_ENV_KEY ≥ 16 chars (recommended 32+ random)

Passphrase that is SHA-256-hashed to derive the 32-byte AES key. If set, all fsParams / dbParams / slParams / lmParams are stored encrypted as { __enc: { iv, tag, data } }. If unset, params are stored in plain form (fine for a laptop, strongly discouraged on a cloud host).

Operational warning: treat this like a database password. If you lose it, freezr cannot decrypt existing credentials and the server will fail to start with FREEZR_ENV_KEY is required to decrypt stored params. If you change it, existing encrypted credentials become unreadable — you'd need to re-enter them.

Database unification strategies — DB_UNIFICATION

MongoDB-based cloud hosts (Atlas, Cosmos DB, etc.) often charge per database or per collection, or cap how many you can create. By default freezr gives every user their own database and every app/table its own collection, which is tidy but explodes on managed hosts. DB_UNIFICATION (mirrored at the preferences level as dbUnificationStrategy) tells the Mongo adapter to consolidate writes. It has three valid values:

ValueDetails
db one DB per user, one collection per app_name.table

Default. No unification. Each user's data lives in a database named after their userId (or in UNIFIED_DB_NAME if useUserIdsAsDbName is off), and each app/table gets its own collection. Cleanest isolation, highest resource count.

allButAdmin one DB + one collection for regular users; admin/system users keep their own

Recommended default for small cloud deployments. Regular user records are all stored in the unified DB (UNIFIED_DB_NAME, default freezr) in a single collection (allUserAppData), tagged with __owner and __appTable fields so queries stay scoped to the right user and app. Reserved/system userIds (fradmin, public, etc.) still get their own database, so admin tables stay separate.

all everyone — including admin/system — shares one DB + one collection

Most aggressive. Every record for every user and every app lives in the same allUserAppData collection of UNIFIED_DB_NAME. Use this when the host caps you at a single database/collection.

Under a unified strategy, freezr rewrites record _ids to include the owner, stamps each document with __owner and __appTable, and filters every read / update / delete by those fields so apps still only see their own rows. UNIFIED_DB_NAME (above) controls the logical database name; the collection name is always allUserAppData.

Important: DB_UNIFICATION is not safely changeable after data has been written — the admin service refuses to update dbUnificationStrategy once it is set, and the startup sequence throws db process unification mismatch if the env var disagrees with what's stored in the admin prefs. Pick a strategy at first setup and keep it.

install / resource adapters

Resource adapters

freezr treats storage, compute, and LLM providers as pluggable adapters. Each user chooses their own set at account-creation time. The server routes every read and write through the configured adapter; no user data flows through a central freezr service.

File-system adapters

An adapter implements a small interface: read, write, delete, list, getReadStream. Shipped connectors:

AdapterFileNotes
localdbfs_local.mjsDefault. Files stored under users_freezr/<user>/files/. Good for self-hosted servers.
awsdbfs_aws.mjsS3. Uses the user's own AWS credentials.
azuredbfs_azure.mjsAzure Blob Storage.
dropboxdbfs_dropbox.mjsDropbox via OAuth.
googleDrivedbfs_googleDrive.mjsGoogle Drive via OAuth.

On a cloud install you can bootstrap the file-system adapter from environment variables. The top-level FREEZR_FS selects the adapter; the remaining variables supply its credentials. If FREEZR_FS is unset (or set to local), freezr falls back to the local disk under users_freezr/.

VariableUsed whenNotes
FREEZR_FSalwaysOne of dropbox, aws, azure, or local (default).
FS_TOKENFREEZR_FS=dropboxDropbox access token.
FS_REFRESH_TOKENFREEZR_FS=dropboxDropbox refresh token (preferred over a short-lived access token).
FS_CLIENTIDFREEZR_FS=dropboxDropbox OAuth client id.
FS_REDIRFREEZR_FS=dropboxOAuth redirect URI.
FS_C_CHALL / FS_C_VERFREEZR_FS=dropboxPKCE code challenge and verifier.
FS_ACCESS_KEY_IDFREEZR_FS=awsAWS access key id.
FS_SECRET_ACCESS_KEYFREEZR_FS=aws or azureAWS secret access key / Azure secret access key.
FS_BUCKETFREEZR_FS=awsS3 bucket name (if blank, freezr can create one with the rights on the key).
FS_STORAGE_ACCOUNT_NAMEFREEZR_FS=azureAzure storage account. Mandatory for the azure adapter.
FS_MS_CONNECTION_STRINGFREEZR_FS=azureConnection string. Only needed if the server is not running on the same Azure backend.
FS_CONTAINER_NAMEFREEZR_FS=azureAzure container name.
REPL_IDautoAuto-detected. Forces local storage with choice: 'replit'.

Google Drive has no environment-variable bootstrap — it is configured per-user through the in-app OAuth flow at /accounts/resources.

Database adapters

An adapter implements query, create, read, update, delete, count, plus index / schema helpers. Collection names are scoped per app (<app_id>.<table>). Shipped connectors:

AdapterFileNotes
nedbdbApi_nedb.mjsEmbedded, file-backed. Zero-config default — used for dev and small deployments.
mongodbdbApi_mongodb.mjsFull MongoDB. Dangerous operators ($where, $function, $accumulator, $expr) are blocked server-side before the query reaches the driver.

Queries pass through dsManager and userDsMgr before hitting the adapter — this is where per-record size limits (2 MB), rate limiting, regex safety, and per-user caching are enforced.

Like the file-system, the default database can be bootstrapped from environment variables. The top-level FREEZR_DB selects the adapter and the remaining variables supply its connection details. If FREEZR_DB is unset, freezr auto-detects what is available (a local mongo on 27017 or NeDB on disk).

NeDb Rocks!

Even though NeDb is not meant to be used for large implementations, the fact is that your personal server collections won't run into millions of records too quickly, so NeDb is a great way to start.. and perhaps continue - NeDb has managed 10,000+ records per file without any prolems.

VariableUsed whenNotes
FREEZR_DBalwaysOne of nedb, mongodb, or cosmosformongostring.
MONGO_STRFREEZR_DB=mongodb or cosmosformongostringFull MongoDB / Cosmos-for-Mongo connection string (e.g. from Atlas). Takes precedence over the host/user/pass variables below.
DB_HOSTFREEZR_DB=mongodb (no MONGO_STR)MongoDB host.
DB_PORTFREEZR_DB=mongodb (no MONGO_STR)MongoDB port.
DB_USERFREEZR_DB=mongodb (no MONGO_STR)MongoDB user.
DB_PASSFREEZR_DB=mongodb (no MONGO_STR)MongoDB password.
ADD_AUTHFREEZR_DB=mongodbTruthy to append auth info to the connection string. Default false.
UNIFIED_DB_NAMEFREEZR_DB=mongodb or cosmosformongostringName of the logical database inside the cluster. Defaults to freezrDb (mongo) or freezr (cosmos). Also used as the shared DB under a unified strategy.
DB_UNIFICATIONFREEZR_DB=mongodbCloud consolidation strategy: db (default, one DB per user), allButAdmin, or all. See Database unification strategies. Must match the admin-saved dbUnificationStrategy and is fixed after first setup.
⚠ Some Quirks

Some databases require manual indexing. If you notice slow queries after adding data, check that the relevant fields are indexed for your chosen adapter.

If using Azure's Cosmos specifically, you would need to build composite index of _id and _date_modified (in mongo shell: use freezr then
db.allUserAppData.createIndex({ "_date_modified": -1, "_id": -1 }, { name: "dateModified_id" }))
and also
db.allUserAppData.createIndex({ __owner: 1, __appTable: 1, isPublic: 1, doNotList: 1, _date_published: -1 })
You could also do a catchall db.allUserAppData.createIndex({ "$**": 1 }) .. or

LLM connectors

LLM connectors normalise provider-specific protocols behind freezr.llm.ask and freezr.llm.generateImage. The user supplies their own API keys in their account settings; freezr never proxies through a central key. Streaming is handled via server-sent events regardless of provider.

ProviderNotes
ClaudeAnthropic API. Supports extended thinking (thinking: true or { budget_tokens }). Images: SVG generated then server-side rasterised to PNG.
ChatGPTOpenAI API. Supports reasoning effort (thinking: { effort: 'low'|'medium'|'high' }) and auto-selects o-series models. Images via gpt-image.

LLM keys are not configured via process.env. Each user enters their own Claude / ChatGPT key at /accounts/resources and it is stored encrypted (with FREEZR_ENV_KEY, when set) in their own lmParams record.