3 ‐ Central Server - Bento-Project-SCARS/ProjectSCARS GitHub Wiki
Central Server
The central server is written in Python using the FastAPI framework and utilizes SQLite, MySQL, or PostgreSQL as its database, depending on the selected configuration. It also uses either a pure-Python file object storage or a third-party S3-compatible object storage for storing user avatars and exported PDFs. It is responsible for handling the backend logic and storing the submitted data of canteen managers.
Requirements
The hard requirements are as follows:
Development Setup
-
Install the required software.
-
Clone the repository.
git clone https://github.com/Bento-Project-SCARS/ProjectSCARS.git
-
Navigate to the
CentralServer
directory.cd ProjectSCARS/CentralServer
-
Install dependencies.
uv sync
-
Copy and edit the configuration file.
cp .config.example.json config.json uv run ./scripts/secret.py sign # Generate secure secret keys uv run ./scripts/secret.py encrypt # and write it to `config.json` uv run ./scripts/secret.py refresh
Edit the
config.json
file to their appropriate values. -
Select the database you want to use. See Database Setup for more information.
-
Select the object store you want to use. See Object Store Setup for more information.
-
Set up SMTP Connections.
-
Enable OAuth Integrations.
-
Run the FastAPI development server.
uv run fastapi dev centralserver --host 0.0.0.0 --port 8081 # Run it using fastapi uv run uvicorn centralserver:app --host 0.0.0.0 --port 8081 # Run it using uvicorn uv run -m centralserver # Run the server directly (using `config.json` values for host and port)
[!IMPORTANT] The default credentials are:
- username:
bento
- password:
ProjectSCARS1
Environment Variables
The following environment variables are used by the central server to further configure its behavior. These variables are optional.
Environment Variable | Value | Description |
---|---|---|
CENTRAL_SERVER_CONFIG_FILE |
./config.json |
The path of the configuration file to use. |
CENTRAL_SERVER_CONFIG_ENCODING |
utf-8 |
The encoding of the configuration file. |
[!TIP] If you want to use a different configuration file, you can run the following:
For Linux users:
CENTRAL_SERVER_CONFIG_FILE=.config.dev.json uv run fastapi dev centralserver --host 0.0.0.0 --port 8081
For Windows users:
$env:CENTRAL_SERVER_CONFIG_FILE=".config.dev.json"; uv run fastapi dev centralserver --host 0.0.0.0 --port 8081
Resetting Central Server Data
While contributing to the project, you might have to start your database and object store from scratch.
Because of this, you can run scripts/clean.py
to reset them.
# Clean the database and object store configured in config.json:
uv run ./scripts/clean.py
# Clean the database and object store configured in another config file:
uv run ./scripts/clean.py --config CONFIG_FILEPATH
Database Setup
The central server supports the following databases:
- SQLite (default)
- MySQL
- PostgreSQL
SQLite Database
To start using SQLite, just edit ./CentralServer/config.json
and adjust the
database
property to use SQLite. The connect_args
property is optional
and can be used to pass additional SQLAlchemy connection arguments.
{
/* ... */
"database": {
"type": "sqlite",
"config": {
"filepath": "database.db",
"connect_args": {
// SQLAlchemy connection arguments
}
}
}
/* ... */
}
On startup, the central server will create a SQLite database file
in the file path specified in the filepath
property. The default
is centralserver.db
in the root directory of the central server.
This database is sufficient for development and testing purposes, but for production use, it is recommended to use MySQL or similar database server.
MySQL Database
Since SQLite is a file-based database and lacks the ability to run multiple instances, it is not suitable for production use which needs high throughput and availability. Therefore, the central server also supports MySQL as a database. The MySQL database can be run in a containerized environment using Docker or Podman.
-
Create a
.env
file in./CentralServer/system/mysql/
using the example file.cd ./system/mysql/ cp .env.example .env
-
Adjust the environment variables in
./CentralServer/system/mysql/.env
. For more information about MySQL Docker environment variables, see their documentation. -
Run the MySQL container.
docker-compose up -d # Run this if you are using Docker. podman-compose up -d # Run this if you are using Podman. cd ../..
-
If successful, you should be able to access PHPMyAdmin at
http://localhost:8083
.
[!IMPORTANT] You might need to log in as the root user in the database in the future. The root password is randomly generated, which can be seen in the logs of the MySQL container with the following format:
[Note] [Entrypoint]: GENERATED ROOT PASSWORD: bfPy...lqLL
-
Update
./CentralServer/config.json
to use MySQL. Use the same database credentials as the ones in the.env
file. Theconnect_args
property is optional and can be used to pass additional SQLAlchemy connection arguments.{ /* ... */ "database": { "type": "mysql", "config": { "username": "ProjectSCARS_DatabaseAdmin", "password": "ProjectSCARS_mysql143", "host": "localhost", "port": 3306, "database": "ProjectSCARS_CentralServer", "connect_args": { // sqlalchemy connection arguments } } } /* ... */ }
PostgreSQL Database
Another option is to use PostgreSQL as a database. Like the MySQL adapter, you can run PostgreSQL with minimal configuration by following these steps:
-
Create a
.env
file in./CentralServer/system/postgresql/
using the example file.cd ./system/postgresql/ cp .env.example .env
-
Adjust the environment variables in
./CentralServer/system/postgresql/.env
. For more information about PostgreSQL Docker environment variables, see their documentation. -
Run the PostgreSQL container.
docker-compose up -d # Run this if you are using Docker. podman-compose up -d # Run this if you are using Podman. cd ../..
-
If successful, you should be able to access Adminer at
http://localhost:8083
. -
Update
./CentralServer/config.json
to use PostgreSQL. Use the same database credentials as the ones in the.env
file. Theconnect_args
property is optional and can be used to pass additional SQLAlchemy connection arguments.{ /* ... */ "database": { "type": "postgres", "config": { "username": "ProjectSCARS_DatabaseAdmin", "password": "ProjectSCARS_postgres143", "host": "localhost", "port": 5432, "database": "ProjectSCARS_CentralServer", "connect_args": { // sqlalchemy connection arguments } } } /* ... */ }
Object Store Setup
The central server supports the following object stores:
- Local file object store (default)
- MinIO S3-Compatible Object Store
- Garage S3-Compatible Object Store
- Cloudflare R2 Object Store
Local File Object Store
To start using the local file object store, just edit
./CentralServer/config.json
and adjust the object_store
property to match the following structure:
{
/* ... */
"object_store": {
"type": "local",
"config": {
"filepath": "./data/"
}
}
/* ... */
}
When the central server starts, it will use the provided
filepath to store the files (objects). Make sure that the
filepath is writable by the server. The default is ./data/
in the root directory of the central server. It is already
created in the repository, so no further action is needed.
Because the local file object store is implemented in the central server itself, it does not provide any integrity and redundancy systems. Therefore, it is recommended to use a dedicated object store for production use, and use the local file object store only for development purposes.
MinIO S3-Compatible Object Store
Using MinIO, it is possible to provide multiple nodes to store the objects. This is useful for redundancy and high availability, therefore it is recommended to be used in production. The MinIO object store can be run in a containerized environment using Docker or Podman.
-
Create a
.env
file in./CentralServer/system/minio/
using the example file.cd ./system/minio/ cp .env.example .env
-
Adjust the environment variables in
./CentralServer/system/minio/.env
. -
Run the MinIO container.
docker-compose up -d # Run this if you are using Docker. podman-compose up -d # Run this if you are using Podman. cd ../..
-
If successful, you should be able to access the MinIO dashboard at
http://localhost:8084
. -
Log in to the dashboard using the credentials in the
.env
file. -
Navigate to the
Access Keys
tab and create a new access key. Make sure to copy the keys, as they will not be shown again. -
Edit
./CentralServer/config.json
and adjust theobject_store
to match the following structure:{ /* ... */ "object_store": { "type": "minio", "config": { "endpoint": "localhost:9000", "access_key": "YOUR_ACCESS_KEY", "secret_key": "YOUR_SECRET_KEY", "secure": false } } /* ... */ }
Garage S3-Compatible Object Store
Garage is another free and open-source S3-compatible object store that can be used with the central server. It is similar to MinIO, but it is designed to be lightweight and easy to use. To use Garage, you can follow the steps below:
-
Create a
garage.toml
file in./CentralServer/system/garage/
using the example file.cd ./system/garage/ cp garage.example.toml garage.toml
-
Open
garage.toml
and adjust the values accordingly. For more information, read Garage's documentation. As a quick start, update the following values usingopenssl rand -hex 32
(Linux) or[System.Security.Cryptography.RandomNumberGenerator]::GetBytes(32) | ForEach-Object ToString X2 | Join-String
(Windows PowerShell).rpc_secret
admin_token
metrics_token
-
Run the Garage container.
docker-compose up -d # Run this if you are using Docker. podman-compose up -d # Run this if you are using Podman. cd ../..
-
Now, you have Garage running. Run the following command to see the status of Garage:
# CONTAINER_NAME would be `garage-centralserver-garage-1` in Podman # For Docker, it would be `centralserver-garage-1` docker exec -ti CONTAINER_NAME /garage status
-
Next, you will have to create a cluster layout.
[!NOTE] Creating a cluster layout for a Garage deployment means informing Garage of the disk space available on each node of the cluster as well as the zone (e.g. datacenter) each machine is located in.
docker exec -ti CONTAINER_NAME /garage layout assign -z ph1 -c 5G NODE_ID
This command will...
-
Set the zone of the node to ph1 (
-z ph1
) -
Set the capacity of the node to 5G (
-c 5G
)You will have to adjust the values to your needs.
NODE_ID
is the ID shown in thegarage status
command (first column).
-
Now that you have set the layout of the cluster, you will now have to commit the changes. Run the following command to do so:
# Set the current layout as the first version of the configuration podman exec -ti CONTAINER_NAME /garage layout apply --version 1
-
Now, you will have to generate an API key using Garage's CLI application for the central server. Run the following:
docker exec -ti CONTAINER_NAME /garage key create centralserver-app-key docker exec -ti CONTAINER_NAME /garage key allow --create-bucket centralserver-app-key
It should show you something similar the following:
==== ACCESS KEY INFORMATION ==== Key ID: GK**********************eb Key name: centralserver-app-key Secret key: 63************************************************************12 Created: 2025-06-01 16:17:23.884 +00:00 Validity: valid Expiration: never Can create buckets: false ==== BUCKETS FOR THIS KEY ==== Permissions ID Global aliases Local aliases
-
From the output of the previous step, copy the Key ID and the Secret Key. Edit
./CentralServer/config.json
and adjust theobject_store
to match the following structure:{ /* ... */ "object_store": { "type": "garage", "config": { "endpoint": "localhost:3900", "access_key": "YOUR_ACCESS_KEY", "secret_key": "YOUR_SECRET_KEY", "secure": false } } /* ... */ }
Cloudflare R2 Object Store
Cloudflare R2 is a free S3-compatible object store that can be used with the central server. To use Cloudflare R2, you can follow the steps below:
- Create a new Cloudflare R2 bucket in your Cloudflare account.
- Create a new API key in your Cloudflare account.
- Edit
./CentralServer/config.json
and adjust theobject_store
to match the following structure:
{
/* ... */
"object_store": {
"type": "minio",
"config": {
"endpoint": "https://YOUR_ACCOUNT_ID.r2.cloudflarestorage.com",
"access_key": "YOUR_ACCESS_KEY",
"secret_key": "YOUR_SECRET_KEY",
"secure": true
}
}
/* ... */
}
[!NOTE] The object store type is set to
minio
because Cloudflare R2 is S3-compatible and can be used with the MinIO client. This is not a typographical error, but rather a design choice to maintain compatibility with the existing MinIO implementation in the central server.
SMTP Connection
To enable email notifications, password resets, and other email-related functionality, you have to connect the central server to an SMTP server.
Gmail SMTP Connection
The most basic approach is to use Gmail as the SMTP server. Just follow the instructions in the link below to create an app password:
https://support.google.com/accounts/answer/185833
This is a 16-character-long string, grouped by 4 characters and separated by spaces. Remove the spaces and you will get your app password. After you have successfully created an app password, update your configuration file:
{
/* ... */
"mailing": {
"enabled": true,
"server": "smtp.gmail.com",
"port": 587,
"from_address": "[email protected]",
"username": "[email protected]",
"password": "your-app-password",
"templates_dir": "./templates/mail/",
"templates_encoding": "utf-8"
}
/* ... */
}
Enabling Open Authentication (OAuth)
Google OAuth
To enable linking a user's account with Google OAuth, follow the steps below:
- Go to https://console.cloud.google.com.
- Create a new project if needed. Otherwise, select an existing project.
- Navigate to Google Auth Platform and click "Get Started".
- Follow the steps displayed in the page.
- After setting up the OAuth configuration, create a new OAuth client.
- Set the Application Type to "Web application".
- Set the Authorized JavaScript origins to the web client base URL.
- Set the Authorized redirect URIs to the central server base URL.
- Get the client ID and client secret and paste it to
config.json
.
{
/* ... */
"authentication": {
"oauth": {
"google": {
"client_id": "UPDATE_THIS_VALUE",
"client_secret": "UPDATE_THIS_VALUE",
"redirect_uri": "http://localhost:8080/login/oauth/google"
}
}
}
/* ... */
}
Microsoft OAuth
This has not yet been implemented.
Facebook OAuth
This has not yet been implemented.