AFFiNE: Member Limit Resetting On Container Restart

Alex Johnson
-
AFFiNE: Member Limit Resetting On Container Restart

Hey there, fellow AFFiNE enthusiasts! If you're running the self-hosted version of AFFiNE and have bumped into the pesky issue of the member limit resetting every time your container restarts, you're definitely not alone. It's a frustrating hiccup that can put a damper on your collaborative workspace. But don't worry, we're going to dive deep into this problem, explore why it's happening, and, most importantly, find a solution! Let's get started.

The Annoying Member Limit Reset: What's the Fuss About?

So, you're happily using AFFiNE, a fantastic open-source alternative to Notion, and you've hit a limitation: the member limit. By default, the self-hosted version might cap your user count, which can be a real pain if you're running a team or have a larger project. You've likely discovered the workaround, a handy PostgreSQL command to increase that limit:

UPDATE features
SET configs = jsonb_set(configs::jsonb, '{memberLimit}', '100')
WHERE configs::jsonb ? 'memberLimit';

This command is a lifesaver, allowing you to expand your workspace. But here's the kicker: every time you restart your Docker container, poof – the member limit reverts back to its original value. This means you're stuck running the command again and again, which is, let's face it, a major inconvenience. This is precisely the issue we're addressing today.

This behavior is not only annoying but also undermines the self-hosted experience. The beauty of self-hosting is the control and customization it offers. Having to repeatedly reconfigure a setting after every restart defeats the purpose and makes the platform feel less reliable. It's a valid concern, and we're here to help you get to the bottom of it.

Let's clarify what's happening. When you modify the memberLimit using the SQL command, you're directly updating the database where AFFiNE stores its configuration settings. This works perfectly fine until the container restarts. The container, when it boots up, likely initializes its configuration from a default state or from a source that doesn't include your manual database update. Thus, your changes are overwritten. The core of the problem lies in the way AFFiNE loads and applies its configuration on startup.

So, where does this leave you? You have several options, ranging from quick fixes to more permanent solutions. Let's delve into these options and find the best fit for your needs. We'll explore the root cause, potential fixes, and even how to contribute to the project if you're feeling ambitious. Let's keep your AFFiNE experience smooth and hassle-free!

Understanding the Root Cause: Where Does the Reset Happen?

To really tackle this issue, we need to understand why the member limit is resetting. This requires a little bit of detective work into how AFFiNE handles its configuration and database interactions. Unfortunately, without a direct pointer to the source code, we'll have to make some educated guesses based on common practices in similar applications. However, this is still a good starting point.

Database Initialization and Configuration Loading

One of the primary culprits is likely how AFFiNE initializes its database and loads its configurations on startup. Docker containers are designed to be ephemeral. Data persistence often requires explicit handling, such as using volumes to store data outside the container or ensuring that configuration changes are saved in a persistent manner.

Here's a possible scenario: When the container starts, it might execute a series of steps to set up the environment. These steps can include:

  • Database Setup: The container connects to the PostgreSQL database. If the database is not already initialized, the container might execute scripts to create the necessary tables and populate them with default data.
  • Configuration Loading: The application reads its configuration from various sources. This might include environment variables, configuration files, and, of course, the database.
  • Configuration Overriding: The application merges the configurations from different sources. This is where the conflict arises. If the database configuration (with your updated member limit) is loaded after the default configuration, it overrides your changes. Alternatively, if the default configuration is loaded after your manual changes, your changes will be overwritten.

The Role of Default Values

Another possible cause is the presence of default values in the application's configuration. The application may have a hardcoded default value for the member limit (e.g., 10). When the container starts, it might read this default value and apply it, effectively resetting your changes. This is a common practice, particularly for settings that have a reasonable default value.

Identifying the Problematic Code

To identify the exact code responsible for the reset, you would ideally need to:

  1. Examine the Dockerfile: Check the Dockerfile used to build the AFFiNE container. Look for any commands that initialize the database or load configurations. This can give you clues about the startup process.
  2. Inspect the Application Code: Search the AFFiNE codebase for the following:
    • Database connection logic.
    • Configuration loading mechanisms.
    • Any code that interacts with the memberLimit setting.
  3. Monitor Logs: Examine the application logs during startup. These logs can often provide valuable insights into the configuration loading process and identify the exact point where the memberLimit is being set.

Understanding these mechanisms will not only help you resolve the issue but also give you a deeper understanding of how AFFiNE works under the hood. It empowers you to take control of your self-hosted setup and make it work the way you want it to.

Potential Solutions and Workarounds

Okay, so we understand the problem. Now, how do we fix it? Here are a few potential solutions and workarounds you can try:

1. Scripting the SQL Command

This is the simplest, albeit not ideal, solution. Create a script that executes the UPDATE command every time the container starts. This script can be as simple as a shell script that connects to your PostgreSQL database and runs the command. You can add this script to your Dockerfile or execute it using docker-compose. Here's a basic example:

#!/bin/bash

# Wait for PostgreSQL to be ready
sleep 10

# Run the SQL command
psql -h <your_postgres_host> -U <your_postgres_user> -d <your_postgres_db> -c "UPDATE features SET configs = jsonb_set(configs::jsonb, '{memberLimit}', '100') WHERE configs::jsonb ? 'memberLimit';"

echo "Member limit updated."

Make sure to replace <your_postgres_host>, <your_postgres_user>, and <your_postgres_db> with your actual database credentials. This script should be executed after the database is up and running.

Adding the Script to Your Dockerfile

If you're building your own Docker image, you can add this script to the Dockerfile. For example:

# ... your base image and other instructions ...

COPY update_member_limit.sh /

CMD [

You may also like