Buffet is a full-stack, fully-featured web-based virtual machine manager that aims to provide a free, open-source, easy-to-use, secure alternative to other web-based virtual machine managers such as DistroSea and DistroTest.
The back-end is written in Python using the Flask web framework, and the front-end is written in TypeScript with the React library. Buffet uses QEMU and KVM for virtualization, and noVNC + websockify for remote desktop access.
Buffet in its original form was made over the course of 12 weeks as part of the final project for my bachelor's degree in Computer Systems at the School of Mathematical and Computer Sciences at Heriot-Watt University. Since then, I have continued to work on Buffet in my free time to improve it and add new features.
Important
Please note that Buffet is not intended for production use, as it is still in the early stages of development.
However, you are welcome to use it for testing and development purposes. Please report any bugs or issues you encounter on the Issues page. Feel free to contribute to the project by submitting a pull request.
- Access virtual machines securely using noVNC, websockify with SSL/TLS support, and randomly generated, one time VNC passwords
- Administer users, virtual machines and logs from the admin panel
- Create, start, and delete QEMU/KVM virtual machines
- Define custom operating systems and distributions using JSON
- Email-based account verification
- Fully responsive front-end that works on desktops, tablets, and smartphones
- Lightweight, easy-to-setup back-end using Flask and SQLAlchemy
- Runs on GNU/Linux servers with QEMU and KVM support
- Secure user authentication and authorisation using JSON Web Tokens (JWT), bcrypt and two-factor authentication
- Compatible with any relational database supported by SQLAlchemy, such as SQLite, PostgreSQL, MySQL, and MariaDB
The virtual machine view allows you to access your virtual machines using noVNC, and comes with draggable, usable navigation bars.
Buffet is designed to be easy to install and use. It consists of two main components: the front-end and the back-end. The front-end is a React application that communicates with the back-end using a RESTful API. The back-end is a Flask application that provides the RESTful API for the front-end to communicate with.
If you want to host your own instance of Buffet, you will need to install both the front-end and the back-end on your server. A detailed guide on how to install Buffet is provided below. Instructions for installing the front-end, the back-end, and the Docker container are provided in the Docker Compose Installation section. Alternatively, if you just want to install them using the base Docker command, look for the Docker Container Installation in each section.
The front-end is a React application that communicates with the back-end using the RESTful API. It is designed to be lightweight, easy to install, and easy to use.
Note
You can install the front-end on any server that supports Node.js and npm, i.e. on Windows, macOS, or GNU/Linux.
- Node.js v20.10.0 or later
- npm 10.4.0 or later
- Clone the repository:
git clone https://github.com/kgdn/buffet.git
- Change into the
client
directory:
cd client
- Install the required dependencies:
npm install
- Create a .env file in the
client
directory with the following contents:
.env
BROWSER= # none or chrome or firefox or edge or safari
GENERATE_SOURCEMAP= # true or false
VITE_BASE_URL= # url of api (e.g. https://localhost)
VITE_MAX_VM_COUNT= # max no. of virtual machines available at any given time
- Start the development server (optional):
npm run dev
- Build the production version:
npm run build
- Deploy the production version to your server using your preferred method, such as Nginx, Apache, or Caddy.
npm run build && cp -r dist/* /path/to/your/webserver/
Note
This assumes you have followed the steps in the Front-end Installation up until step 4. If you have not done so, please refer to the Front-end Installation section for more details.
It is highly recommended to use the Docker Compose installation method as detailed in the Docker Compose Installation section instead.
- Modify the
nginx/example.conf
file to match your desired configuration. Rename it tonginx.conf
and save it.
mv example.conf nginx.conf
- Build the Docker image:
docker build -t buffet-client .
- Run the Docker container, where
./certs
is the path to the SSL certificates:
docker run -v ./certs:/app/certs/ -p 443:443 --name buffet-client -d buffet-client
The back-end is a Flask application that provides the RESTful API for the front-end to communicate with, allowing for the creation of virtual machines and querying of database data.
Note
Unlike the front-end, the back-end is designed to be installed on a GNU/Linux server, as it makes extensive use of QEMU and KVM for virtualization. You can install the back-end on any GNU/Linux distribution that supports Python 3 and pip. Ensure that you have the required dependencies installed before proceeding.
- Python 3.12.2 or later
- pip 23.2.1 or later
- venv for Python 3
- QEMU 8.1.3 or later
- Any GNU/Linux distribution for the host operating system
- Virtualization support enabled in the BIOS/UEFI settings
- KVM kernel module loaded
Tip
You can check if the KVM kernel module is loaded by running the following command:
lsmod | grep kvm
You should see output similar to the following:
kvm_intel 425984 0
kvm_amd 98304 0
kvm 1376256 1 kvm_intel
irqbypass 12288 1 kvm
If you do not see any output, you may need to load the KVM kernel module manually:
sudo modprobe kvm
Buffet uses SQLAlchemy to interact with the database. A database is required to store user information and virtual machine information. You can use any SQL database supported by SQLAlchemy, such as SQLite, PostgreSQL, MySQL, and MariaDB. You can use a Docker container for this if you prefer.
-
To use SQLite, you can set the
SQLALCHEMY_DATABASE_URI
variable in the.env
file tosqlite:///db.sqlite3
. This requires no additional setup. -
To use PostgreSQL, you can set the
SQLALCHEMY_DATABASE_URI
variable in the.env
file topostgresql://username:password@localhost/dbname
. This assumes that you have a PostgreSQL database running on your server. You may need to install thepsycopg2
package using pip. This is the recommended database for production use. -
To use MySQL/MariaDB, you can set the
SQLALCHEMY_DATABASE_URI
variable in the.env
file tomysql://username:password@localhost/dbname
. This assumes that you have a MySQL database running on your server. You may need to install themysql-connector-python
package using pip.
- Clone the repository:
git clone https://github.com/kgdn/buffet.git
- Change into the
server
directory:
cd server
- Create a virtual environment:
python3 -m venv .venv
- Activate the virtual environment:
source .venv/bin/activate
- Install the required dependencies:
pip install -r requirements.txt
- Create a .env file in the
server
directory with the following contents:
.env
SECRET_KEY= # your secret
SQLALCHEMY_DATABASE_URI= # your_database_uri
SQLALCHEMY_TRACK_MODIFICATIONS= # True or False
SQLALCHEMY_ECHO= # True or False
JWT_SECRET_KEY= # your_secret_key
JWT_COOKIE_CSRF_PROTECT= # True or False
JWT_COOKIE_SECURE= # True or False
JWT_TOKEN_LOCATION= # headers, cookies, query_string or json
JWT_ACCESS_TOKEN_EXPIRES= # access_token_expires (int)
JWT_REFRESH_TOKEN_EXPIRES= # refresh_token_expires (int)
CORS_HEADERS= # Content-Type
MAIL_SERVER= # SMTP server
MAIL_PORT= # SMTP port
MAIL_USERNAME= # your email
MAIL_PASSWORD= # your password
MAIL_DEFAULT_SENDER= # your email
MAIL_MAX_EMAILS= # max_emails (int)
MAIL_ASCII_ATTACHMENTS= # True or False
FRONT_END_ADDRESS= # localhost, 127.0.0.1, etc.
BACK_END_ADDRESS= # localhost, 127.0.0.1, etc.
SSL_CERTIFICATE_PATH= # path_to_ssl_certificate
SSL_KEY_PATH= # path_to_ssl_key
GUNICORN_BIND_ADDRESS= # bind address, i.e. 0.0.0.0:8000
GUNICORN_WORKER_CLASS= # worker class, i.e. gevent
GUNICORN_LOG_LEVEL= # log level, i.e. debug
GUNICORN_ACCESS_LOG= # access log, i.e. gunicorn_access.log
MAX_VM_COUNT= # max no. of virtual machines available at any given time
- Put your virtual machine images in the
iso
directory, and create anindex.json
file in theiso
directory with the following structure:
[
{
"iso": "archlinux.iso", // name of the ISO file
"desktop": "No desktop", // desktop environment
"name": "Arch Linux", // name of the distribution
"version": "Latest", // version of the distribution
"description": "Bleeding edge GNU/Linux distribution where you build your own system from the ground up, tailored to your needs.", // description of the distribution
"linux": true, // whether the distribution uses the Linux kernel or not
"logo": "archlinux.png", // name of the logo file found in the iso/logos directory
"homepage": "https://archlinux.org", // homepage of the distribution
"beginner_friendly": false // whether the distribution is beginner-friendly or not
} // add more distributions here
]
- Create a
logos
directory in theiso
directory and put your distribution logos in it.
mkdir iso/logos
mv archlinux.png iso/logos
- Start the development server (optional):
flask -A app run
- Run the production server (recommended):
gunicorn app:app
Note
This assumes you have followed the steps in the Back-end Installation up until step 8. If you have not done so, please refer to the Back-end Installation section for more details.
It is highly recommended to use the Docker Compose installation method as detailed in the Docker Compose Installation section instead.
- Build the Docker image:
docker build -t buffet-server .
- Run the Docker container, where
./iso
is the path to the virtual machine images and./certs
is the path to the SSL certificates:
docker run -v ./iso:/app/iso -v ./certs:/app/certs -p 8000:8000 --name buffet-server -d buffet-server
An example docker-compose.yml
file is shown below, and is available in the root of the repository here. You should follow the same structure, but change POSTGRES_PASSWORD
, POSTGRES_USER
, and POSTGRES_DB
to your desired values.
services:
client:
build: client/
ports:
- 443:443
volumes:
- ./certs:/app/certs
server:
build: server/
devices:
- "/dev/kvm:/dev/kvm"
volumes:
- ./iso:/app/iso
- ./certs:/app/certs
network_mode: host
database:
image: postgres
environment:
POSTGRES_PASSWORD: postgres # Change this to your desired password
POSTGRES_USER: postgres # Change this to your desired username
POSTGRES_DB: postgres # Change this to your desired database
ports:
- "5432:5432"
volumes:
- db-data:/var/lib/postgresql/data
volumes:
iso:
certs:
db-data:
To build and run the Docker containers, you can use the following commands:
docker compose build
docker compose up
Buffet is an open-source project, and contributions are welcome. If you would like to contribute to Buffet, please follow the standard guidelines for contributing to open-source projects. That is, fork the repository, make your changes, and submit a pull request.
Important
When contributing to Buffet's back-end, please follow the PEP 8 style guide for Python code. Please ensure that your code follows the PEP 8 style guide and that your commit messages are clear and concise. Use the Black code formatter, isort, and pylint to format your code and check for errors.
When contributing to Buffet's front-end, use ESLint, Prettier and Stylelint to format your code and check for errors.
Buffet is licensed under the GNU Affero General Public License v3.0. You are free to use, modify, and distribute Buffet under the terms of the AGPLv3. Please read the LICENSE file for more information.
Buffet uses the following third-party libraries and dependencies:
- Open Sans (Apache License 2.0)
- Bootstrap Icons (MIT License)
- Bootstrap (MIT License)
- @novnc/novnc (MPL-2.0 License)
- @testing-library/jest-dom (MIT License)
- @testing-library/react (MIT License)
- @testing-library/user-event (MIT License)
- @types/jest (MIT License)
- @vitejs/plugin-react (MIT License)
- axios (MIT License)
- bootstrap (MIT License)
- bootstrap-icons (MIT License)
- password-validator (MIT License)
- prop-types (MIT License)
- react (MIT License)
- react-bootstrap (MIT License)
- react-dom (MIT License)
- react-responsive (MIT License)
- react-router-dom (MIT License)
- universal-cookie (MIT License)
- validator (MIT License)
- vite (MIT License)
- web-vitals (Apache-2.0 License)
- cef (Mozilla Public License 2.0)
- Flask (BSD-3 License)
- Flask-Bcrypt (MIT License)
- Flask-Cors (MIT License)
- Flask-JWT-Extended (MIT License)
- Flask-Limiter (MIT License)
- Flask-Mail (BSD-3 License)
- Flask-Migrate (MIT License)
- Flask-SQLAlchemy (MIT License)
- Gunicorn (MIT License)
- KVM (GPLv2, extended by the Linux kernel)
- QEMU (GPLv2)
- SQLAlchemy (MIT License)
- websockify (LGPLv3)