Virtual Server (PHP 7.4)
This guide explains how to deploy a Brezel instance to a (virtual) server.
For this guide, we assume the base domain is called example.io and Brezel will be accessible under brezel.example.io.
The example IP of the server is given as 5.35.243.342.
Prerequisites
- Root access
- Ubuntu or Debian
- Nginx
- GitLab repository for your Brezel instance
0. Install Nginx, PHP, MySQL/MariaDB and Certbot
apt-get updateapt-get install nginx certbot python3-certbot-nginx php7.4-fpm php7.4-curl php7.4-gd php7.4-xml php7.4-zip php7.4-mysqlInstall MariaDB using a guide like this.
1. Add DNS records
Login to your external DNS provider and add the following DNS records (replace the bold values with your use case):
| Name | Type | Value |
|---|---|---|
| brezel.example.io | A | 5.35.243.342 |
| *.brezel.example.io | A | 5.35.243.342 |
2. Add the SPA domain
In /etc/nginx/sites-available, create a new file called spa:
server { listen 80; listen [::]:80; server_name brezel.example.io;
location / { root /var/www/vhosts/api.brezel.example.io/dist; index index.html index.htm; try_files $uri $uri/ /index.html; }
# redirect server error pages to the static page /50x.html error_page 500 502 503 504 /50x.html; location = /50x.html { root /var/www/vhosts/api.brezel.example.io/dist; }}Save the file, then create a symlink:
ln -s /etc/nginx/sites-available/spa /etc/nginx/sites-enabled/spaRestart NGINX:
systemctl restart nginxSecure the SPA domain
sudo certbot --nginx -d brezel.example.io3. Add the API domain
In /etc/nginx/sites-available, create a new file called api:
server { listen 80; listen [::]:80; server_name api.brezel.example.io;
root /var/www/vhosts/api.brezel.example.io/public;
add_header X-Frame-Options "SAMEORIGIN"; add_header X-Content-Type-Options "nosniff";
# Add index.php to the list if you are using PHP index index.php index.html index.htm index.nginx-debian.html;
charset utf-8;
location / { try_files $uri $uri/ /index.php?$query_string; gzip_static on; }
location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \.php$ { fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; include snippets/fastcgi-php.conf; }}Save the file, then create a symlink:
ln -s /etc/nginx/sites-available/concepts /etc/nginx/sites-enabled/conceptsEnsure these values in your top level/etc/nginx/nginx.conf file:
worker_processes auto;
events { worker_connections 2048;}They have already been set, be sure to change the values and not just add a new line with the same directive.
Configure your php-fpm settings in /etc/php/7.4/fpm/pool.d/www.conf:
pm = dynamicpm.max_children = 300pm.start_servers = 20pm.min_spare_servers = 20pm.max_spare_servers = 50pm.process_idle_timeout = 15spm.max_requests = 300You can either just paste these values at the end of the file or search for the values and change them.
Finally, add the following values to your /etc/php/7.4/fpm/php.ini file:
opcache.enable=1opcache.enable_cli=1opcache.memory_consumption=256opcache.interned_strings_buffer=16opcache.max_accelerated_files=10000opcache.revalidate_freq=300Restart Nginx:
systemctl restart nginxSecure the API domain
sudo certbot --nginx -d concepts.brezel.example.io4. Configure Brotcast
Brotcast is a websocket server that is used for real-time communication between the Brezel instance and the frontend.
Installation
Run via Laravel Reverb New
Available since: brezel/api@1.0.0 Since 1.0.0, Brezel ships with a Laravel Reverb based Brotcast server integrated! Once you setup Supervisor, the server will be started automatically. In this case you only need to configure the nginx proxy
Run it via docker compose
Make sure you have docker installed.
Then create a docker-compose.yml file with the following content:
services: brotcast: image: registry.kiwis-and-brownies.de/kibro/brezel/brotcast-server:latest ports: - "8086:8086" environment: - SOKETI_PORT=8086 - SOKETI_DEFAULT_APP_ID=brotcast - SOKETI_DEFAULT_APP_KEY=brotcast-pusher - SOKETI_DEFAULT_APP_SECRET=<a alphanumerical secret>Run docker compose up in the same directory.
Add the domain
In /etc/nginx/sites-available, create a new file called brotcast:
map $http_upgrade $connection_upgrade { default upgrade; '' close;}
upstream brotcast { server 127.0.0.1:8086; # When hosted via docker compose or laravel reverb}
server { listen 80; listen [::]:80;
server_name ws.brezel.example.io;
location / { proxy_pass http://brotcast; proxy_http_version 1.1;
# Dynamic Connection header based on upgrade request proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade;
# Additional headers for better proxy handling proxy_set_header Host $http_host; proxy_set_header Scheme $scheme; proxy_set_header SERVER_PORT $server_port; proxy_set_header REMOTE_ADDR $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }}Save the file, then create a symlink:
ln -s /etc/nginx/sites-available/brotcast /etc/nginx/sites-enabled/brotcastRestart Nginx:
systenctl restart nginxSecure the Brotcast domain
sudo certbot --nginx -d ws.brezel.example.io;5. Create a new user and environment for Brezel
- Create the new user.
adduser brezel- Add your new user to the
www-datagroup to ensure the correct permissions for the Nginx web server.
usermod -aG www-data brezelSet up a basic environment for the new user by copying the /etc/skel directory.
cp -r /etc/skel /home/brezel/- Change the ownership of the copied
/etc/skeldirectory to the new user.
chown -R brezel:www-data /home/brezel/Performance tweaks
You might want to take a look at https://laravel.com/docs/11.x/reverb#production for some possible performance considerations.
Especially increasing the available ports / file descriptors as well as switching to a different runtime might be beneficial.
6. Connect the server to GitLab
The Brezel instance will be deployed to the API subdomain.
The SPA domain will receive the contents of the minified frontend found in the dist/ folder.
Create SSH keys for GitLab
- Switch to the new user.
su - brezel- Generate an RSA key pair:
ssh-keygen -b 4096This will output:
Generating public/private rsa key pair.Enter file in which to save the key (/var/www/vhosts/brezel.example.io/.ssh/id_rsa):The path is fine. Hit enter.
Created directory '/var/www/vhosts/brezel.example.io/.ssh'.Enter passphrase (empty for no passphrase):No passphrase. Hit enter.
Enter same passphrase again:Hit enter. It will then output something like this:
Your identification has been saved in /var/www/vhosts/brezel.example.io/.ssh/id_rsa.Your public key has been saved in /var/www/vhosts/brezel.example.io/.ssh/id_rsa.pub.The key fingerprint is:SHA256:hcsvjIXxM8ZS16X3IHIoGFwPSHr5Cjw35HOIZMEIW1c brezel@lvps5-35-243-342.dedicated.hosteurope.deThe key's randomart image is:+---[RSA 4096]----+|...oo+Eoo . || o...oo+ + o o ||. + * + * = o || + = X = o o o || = O S .|| + @ + || o o . || . || |+----[SHA256]-----+Now, go to GitLab, to the repository of your Brezel instance and go to Settings > Repository > Deploy Keys.
We want our server to be able to read from the GitLab repository.
Paste the contents of ~/.ssh/id_rsa.pub to the Key field. Give it a meaningful title like Production [brezel.example.io].
Clone the repository
- Move to your new user’s web root directory where we will clone the Laravel repository.
cd /var/www/vhosts- Install Git if it’s not already installed.
sudo apt-get install gitClone the instance repository:
git clone git@gitlab.kiwis-and-brownies.de:kibro/basedonbrezel/example.git concepts.example.brezel.ioGo to the cloned directory:
cd concepts.example.brezel.io7. Set up Brezel
Install composer and do
mv composer.phar ~/bin/composerEnter your private package credentials:
Only needed if you don’t deploy via a pipeline Change $PACKAGE_TOKEN and $PACKAGE_TOKEN_USER to a GitLab token and user that can read brezel/api
php ~/bin/composer config --auth gitlab-token.gitlab.kiwis-and-brownies.de $PACKAGE_TOKEN_USER "$PACKAGE_TOKEN"Then, install dependencies:
Only needed if you don’t deploy via a pipeline
php ~/bin/composer installIf you want to merge pdf files or use file thumbnails, you need to install ghostscript and the php imagick extension respectively.
Update folder permissions for the storage directory:
chmod -R 775 storageNext, configure your environment:
Database
Adjust your database configuration in /etc/mysql/my.conf by adding this block to the very bottom:
[mysqld]max_connections = 500innodb_buffer_pool_size = 4Ginnodb_log_file_size = 512Minnodb_log_buffer_size = 16Mmax_allowed_packet = 64MIf you are running MariaDB add the following options too:
thread_pool_size = 100query_cache_size = 64MNow restart the database (Use mariadb if you are running MariaDB):
systemctl restart mysqlFor the database credentials:
Variant 1: Use root credentials
TENANCY_DATABASE="brezel"TENANCY_USERNAME="root"TENANCY_PASSWORD="<password>"Variant 2: Use a privileged database user
Or, if you have root privileges, you can give the brezel MySQL/MariaDB user SUPER privileges:
GRANT SUPER ON *.* TO 'brezel'@'localhost';FLUSH PRIVILEGES;And set the following credentials:
TENANCY_DATABASE="brezel"TENANCY_USERNAME="brezel"TENANCY_PASSWORD="<password>"Setting up the brotcast environment
Configure the brotcast environment in the .env file:
# Broadcasting settings# This url should point to a brezel/brotcast-server instanceBROADCAST_DRIVER=pusherBREZEL_BROTCAST_HOST=ws.brezel.example.ioBREZEL_BROTCAST_PORT=443BREZEL_BROTCAST_APP_ID=brotcastBREZEL_BROTCAST_KEY=brotcast-pusherBREZEL_BROTCAST_SECRET=<the same alphanumerical secret as set in the docker-compose.yml from the setting up brotcast step>BREZEL_BROTCAST_SCHEME=httpsBREZEL_BROTCAST_APP_CLUSTER=mt1Initialization
If the database credentials were set up, you can initialize the instance with
php bakery initNow, you can add your system
php bakery system create exampleAnd fill it with your config:
php bakery applyphp bakery load8. Configure system permissions
- Make sure that everything inside the vhost directory is owned by
brezel:www-data. storage/appshould be owned bywww-data:www-data.storage/frameworkshould also be owned bywww-data:www-data.
9. Set up Brezel SPA
Follow the SPA instructions in the Pipeline guide.
10. Set up the pipeline
Follow the Pipeline guide.
11. Install and configure supervisor
For async workflows and other background jobs to work, we need to install supervisor.
apt-get updateapt-get install supervisorNow copy supervisor.conf.example to supervisor.conf and adjust the socket names if desired.
Then run the following command to create the supervisor configuration:
php bakery make:supervisorNow start supervisor in your instance directory with:
supervisord -c supervisord.confYou probably need to do this as a root user if you run into permission issues for the storage directory!
sudo supervisord -c supervisord.conf
Check that all jobs are up and running:
supervisorctl status12. Set up crons
If you want to use event/cron, you need to set up a cronjob.
Very basically: this should trigger php bakery schedule in the directory of your instance every minute as the user that normally runs your brezel (when using nginx and following this setup it will be www-data).
How you achieve this depends on you, especially on your local setup, but on a server it makes sense to use cron.
For that, switch to a user with the necessary permissions (aka. root or a user that has access to sudo) and edit the crontab of the www-data user.
For that run
sudo crontab -u www-data -eand add the following line:
* * * * * cd /var/www/vhosts/your.brezel.system && php bakery schedule >> /dev/null 2>&1Finally, verify that this was saved correctly by running crontab -u www-data -l and checking if the line is there.