# Installation of part-db on my nginx server at kuschel.at Date: 2025-10-29 KW4NZ Thomas Kuschel Debian Version: (/etc/debian_version) ``` ssh kuschel cat /etc/debian_version ``` A: `13.1` , i.e. trixie ``` ssh kuschel cat /etc/os-release ``` ... to receive more information ## Checks Only available on a PC with credentials to kuschel.at via SSH These settings should be established via the meeting server jitsi ### Check if yarn is installed at mycarbon.at or kuschel.at ``` ssh kuschel yarn --version ``` A: `1.22.22` ### Check if nodejs is installed ``` ssh kuschel nodejs --version ``` A: `24.11.0` ### Check the database MariaDB ``` ssh kuschel mariadb --version ``` A: `mariadb from 11.8.3-MariaDB, client 15.2 for debian-linux-gnu (x86_64) using EditLine wrapper` ### Check the php version ``` ssh kuschel php --version ``` A: `PHP 8.4.14 (cli) (built: Oct 27 2025 21:20:52) (NTS) Copyright (c) The PHP Group Built by Debian Zend Engine v4.4.14, Copyright (c) Zend Technologies with Zend OPcache v8.4.14, Copyright (c), by Zend Technologies` ## Installation ### Create a folder for Part-DB (partdb) Please create a folder for Part-DB and proceed with downloading it. We have completed the installation of all prerequisites and are now prepared to proceed with the Part-DB installation. The next step is to create a folder for Part-DB in the webroot of Apache2/nginx and download it to this folder. The software is downloaded via Git, facilitating straightforward updates at a later date. ``` ssh kuschel ``` ``` sudo git clone https://github.com/Part-DB/Part-DB-symfony.git /var/www/partdb ``` Make it available for nginx user, first check the name of the user with: ``` user=$(grep "user" /etc/nginx/nginx.conf | tr -d ';' | cut -d " " -f 2) | echo $user ``` Change the owner of the directory recursively ``` sudo chown -R $user':' /var/www/partdb ``` ### Create configuration for Part-DB from a template ``` sudo cp /var/www/partdb/.env /var/www/partdb/.env.local ``` Now you have to edit the created file `.env.local`, e.g. with ``` sudo nano -cl /var/www/partdb/.env.local ``` We will show this file to you right here: ``` ... ########################## # Database settings ########################## # Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url # IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml # Use a file (SQLite) as database. For bigger instances you should use a real database server (like MySQL) # DATABASE_URL="sqlite:///%kernel.project_dir%/var/app.db" # Uncomment this line (and comment the line above to use a MySQL database # DATABASE_URL=mysql://root:@127.0.0.1:3306/part-db?serverVersion=5.7 DATABASE_URL=mysql://partdb:wRHEFShdB9gG@127.0.0.1:3306/partdb # Set this value to 1, if you want to use SSL to connect to the MySQL server. It will be tried to use the CA certificate # otherwise a CA bundle shipped with PHP will be used. # Leave it at 0, if you do not want to use SSL or if your server does not support it DATABASE_MYSQL_USE_SSL_CA=0 # Set this value to 0, if you don't want to verify the CA certificate of the MySQL server # Only do this, if you know what you are doing! DATABASE_MYSQL_SSL_VERIFY_CERT=1 # Emulate natural sorting of strings even on databases that do not support it (like SQLite, MySQL or MariaDB < 10.7) # This can be slow on big databases and might have some problems and quirks, so use it with caution DATABASE_EMULATE_NATURAL_SORT=0 ... ``` ### Configuration of the MySql database #### Create a new database "partdb" ```sudo mariadb -p``` You have to enter the root password of the MariaDB database to git into it. An SQL shell opens, the following commands creates a new database and a new user for the program Part-DB. ``` CREATE DATABASE partdb; GRANT ALL PRIVILEGES ON partdb.* TO 'partdb'@'localhost' IDENTIFIED BY 'wRHEFShdB9gG'; ``` Finaly, save the changes with: ``` FLUSH PRIVILEGES; ``` and exit the SQL shell with `exit`. #### Install composer and dependencies for Part-DP Download composer installer script: ``` wget -O /tmp/composer-setup.php https://getcomposer.org/installer ``` Install composer globally ``` sudo php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer ``` ##### Check the composer's version ``` composer --version ``` A: `Composer version 2.8.12 2025-09-19 13:41:59 PHP version 8.4.14 (/usr/bin/php8.4) Run the "diagnose" command to get more detailed diagnostics output.` #### Install composer dependencies (please note the sudo command, to run it under the web server user) First change to the folder partdb with: ``` cd /var/www/partdb ``` Create a cache directory for composer at /var/www/.cache ``` sudo mkdir /var/www/.cache sudo chown www-data: /var/www/.cache ``` ``` sudo -u www-data composer install --no-dev -o ``` ##### Note: Additionally, I had to install the missing ext-bcmath because the tc-lib-barcode requires ext-bcmath, so I installed the package: ``` sudo apt install php-bcmath ``` And again call the `sudo -u www-data composer install --no-dev -o` under the user www-data. #### Install and Run yarn in that directory ``` sudo yarn install ``` A: `yarn install v1.22.22` ``` sudo yarn build ``` A: `yarn run v1.22.22 ... encore production --progress ...` #### Clear Console cache ``` sudo -u www-data php bin/console cache:clear ``` #### Checking the PHP configuration ``` sudo -u www-data php bin/console partdb:check-requirements ``` There should be all green OK's in the console, except pdo_sqlite. For a better performance we installed php-curl: ``` sudo apt install php-curl ``` Also, we got a warning `[WARNING] Opcache configuration can be improved. See https://symfony.com/doc/current/performance.html for more info.` So we changed the following lines at: `/etc/php/8.4/cli/conf.d/10-opcache.ini` ``` ; configuration for php opcache module ; priority=10 zend_extension=opcache.so opcache.jit=off ; ADDED by KW4NZ to configure OPcache for Maximum Performance, Symphony related (Part-DB) ;opcache.memory_consumption=128 opcache.memory_consumption=256 ; The amount of memory for interned strings in Mbytes. ;opcache.interned_strings_buffer=8 ; The maximum number of keys (scripts) in the OPcache hash table. ; Only numbers between 200 and 1000000 are allowed. ;opcache.max_accelerated_files=10000 opcache.max_accelerated_files=20000 ``` #### Database Schema Now you create a database schema with the following command: ``` sudo -u www-data php /var/www/partdb/bin/console doctrine:migrations:migrate ``` As a result we got the following warning line: ``` [notice] Migrating up to DoctrineMigrations\Version20250813214628 [warning] [warning] The initial password for the "admin" user is: 9dd3255565 ``` #### NGINX setup: My nginx/sites-available/kuschel.at ``` ## # You should look at the following URL's in order to grasp a solid understanding # of Nginx configuration files in order to fully unleash the power of Nginx. # https://www.nginx.com/resources/wiki/start/ # https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/ # https://wiki.debian.org/Nginx/DirectoryStructure # # In most cases, administrators will remove this file from sites-enabled/ and # leave it as reference inside of sites-available where it will continue to be # updated by the nginx packaging team. # # This file will automatically load configuration files provided by other # applications, such as Drupal or Wordpress. These applications will be made # available underneath a path with that package name, such as /drupal8. # # Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. ## # Default server configuration # #upstream nodered { # server 127.0.0.1:1880; #} server { listen 80; listen [::]:80; server_name www.kuschel.at kuschel.at; ## sending users to https with no www # return 301 https://www.mycarbon.at$request_uri; root /var/www/kuschel.at; # Add index.php to the list if you are using PHP index index.php index.html index.htm index.nginx-debian.html; location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. try_files $uri $uri/ =404; } # pass PHP scripts to FastCGI server # location ~ \.php$ { include snippets/fastcgi-php.conf; # # # With php-fpm (or other unix sockets): fastcgi_pass unix:/var/run/php/php-fpm.sock; # # With php-cgi (or other tcp sockets): # fastcgi_pass 127.0.0.1:9000; } location /us-license/ { auth_basic "Restricted"; auth_basic_user_file /etc/nginx/.htpasswd; } location = /1945/ { autoindex on; #autoindex_exact_size off; #autoindex_format jsonp; #autoindex_format xml; autoindex_localtime on; } location = /spanisch/ { autoindex on; autoindex_localtime on; } # this is for LETSENCRYPT location ^~ /.well-known/acme-challenge/ { default_type "text/plain"; root /var/www/letsencrypt; } location = /.well-known/acme-challenge/ { return 404; } } server { listen 443 ssl default_server; listen [::]:443 ssl default_server; http2 on; # if ($http_host = git.kuschel.at) { # proxy_pass http://localhost:3000/; # } # since nginx V 1.25+ (we are still at 1.22.x) # listen 443 ssl http2 default_server; # listen [::]:443 ssl default_server; # http2 on; server_name www.kuschel.at kuschel.at; root /var/www/kuschel.at; ssl_certificate /etc/letsencrypt/kuschel.at/fullchain.pem; ssl_certificate_key /etc/letsencrypt/kuschel.at/key.pem; # This should be ca.pem (certificate with the additional intermediate certificate) # See here: https://certbot.err.org/docs/using.html ssl_trusted_certificate /etc/letsencrypt/kuschel.at/ca.pem; #ssl_protocols TLSv1.2 TLSv1.3; ssl_session_timeout 24h; ssl_session_cache shared:SSL:50m; #ssl_session_tickets off; # Prefer the SSL ciphers for ECDSA: (the both TLS-* are for TLS 1.3) ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; # ssl_ciphers TLS-CHACHA20-POLY1305-SHA256:TLS-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384; # Use multiple curves #ssl_ecdh_curve secp521r1:secp384r1; #ssl_prefer_server_ciphers off; ssl_prefer_server_ciphers on; # HSTS (ngx_http_headers_module is required) max-age in seconds add_header Strict-Transport-Security "max-age=63072000" always; # OCSP stapling ssl_stapling on; ssl_stapling_verify on; # This is the IP of the DNS server (in most cases: your router's IP) resolver 213.133.98.98 213.133.99.99 213.133.100.100; index index.html index.htm index.php; # location / { # fastcgi_pass unix:/var/run/php/php-fpm.sock; # } location /1945/ { autoindex on; #autoindex_exact_size off; #autoindex_format jsonp; #autoindex_format xml; autoindex_localtime on; } location /spanisch/ { autoindex on; autoindex_localtime on; } location ~ ^/gimplfest/(.*) { return 301 /gimpelfest/$1; } location /gimplfest/ { autoindex on; autoindex_localtime on; } location /gimpelfest/ { # rewrite ^/gimpelfest/Mitternachtseinlage_4D.mp4 /gimpelfest/Mitternachtseinlage_8D.mp4 last; rewrite ^/gimpelfest/Mitternachtseinlage_4D.mp4 /gimpelfest/Mitternachtseinlage_8D.mp4 redirect; autoindex on; autoindex_localtime on; } location ~ ^/index\.php(/|$) { fastcgi_pass unix:/var/run/php/php-fpm.sock; fastcgi_split_path_info ^(.+\.php)(/.+)$; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; fastcgi_param DOCUMENT_ROOT $realpath_root; internal; } location ~ \.php$ { include snippets/fastcgi-php.conf; # # # With php-fpm (or other unix sockets): fastcgi_pass unix:/var/run/php/php-fpm.sock; # old version: fastcgi_pass unix:/run/php/php8.3-fpm.sock; # # With php-cgi (or other tcp sockets): # fastcgi_pass 127.0.0.1:9000; } location /nodered/ { proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; #proxy_http_version 1.1; #proxy_set_header Upgrade $http_upgrade; #proxy_set_header Connection "upgrade"; proxy_pass http://127.0.0.1:1880/; #include proxy_params; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } location /ui/ { auth_basic "Secure UI area"; auth_basic_user_file /etc/nginx/.htpasswd; proxy_pass http://127.0.0.1:1880/ui/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } location /partdb/ { # error_log /var/log/nginx/parts.error.log; # access_log /var/log/nginx/parts.access.log; try_files $uri /partdb/index.php$is_args$args; } location /bilder/ { auth_basic "Secure Picture area"; auth_basic_user_file /etc/nginx/.htpasswd_bilder; autoindex on; autoindex_localtime on; } location ~* ^/admin/(.+\.(css|js)) { rewrite ^/static/contents/$1 break; proxy_pass http://127.0.0.1:1880; } } ``` -- eof --