Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
install_22_4 [2024/02/07 17:03] – [Install RADIUSdesk] systeminstall_22_4 [2024/09/19 10:20] (current) – [Install MariaDB] system
Line 1: Line 1:
 +<nav type="pills" justified="false">
 +  * [[:user_manuals|Back to Documentation]]
 +  * [[:install_22_4|Install on Ubuntu 22.04]]
 +</nav>
  
-====== Installing RADIUSdesk on Ubuntu 22.04 using Nginx ======+---- 
 + 
 +====== Installation of RADIUSdesk on Ubuntu 22.04 with Nginx ======
 ===== Skills required for the installation ===== ===== Skills required for the installation =====
  
 To install RADIUSdesk, you need sufficient knowledge and experience with Linux: To install RADIUSdesk, you need sufficient knowledge and experience with Linux:
   * Installing the Linux operating system.   * Installing the Linux operating system.
-  * Edit text files from the terminal using a text editor such as Vi or Nano. +  * Editing text files via the terminal with a text editor such as Vi or Nano. 
-  * Install packages from a repository.+  * Installing packages from a repository.
   * You must be familiar with how TCP/IP networks work.   * You must be familiar with how TCP/IP networks work.
  
Line 20: Line 26:
   * We recently switched from CakePHPv3 to CakePHPv4.   * We recently switched from CakePHPv3 to CakePHPv4.
   *  If you manage devices with MESHdesk and APdesk, make sure you also run the instructions that include cake3 so that your system is backwards compatible.   *  If you manage devices with MESHdesk and APdesk, make sure you also run the instructions that include cake3 so that your system is backwards compatible.
-  * The firmware on these devices might still point to the cake3 directory, so we need to include support for this directory.+  * The firmware on these devices may still point to the cake3 directory, so we need to include support for this directory.
 </alert> </alert>
- 
  
 ----------- -----------
  
- +===== What we need =====
-===== What do we need =====+
  
   *A standard Nginx installation on Ubuntu is actually very simple.   *A standard Nginx installation on Ubuntu is actually very simple.
-  * The more complicated part is customising Nginx for the following tasks:+  *  The more complicated part is customizing Nginx for the following tasks:
  
 <panel type="default" no-body="true"> <panel type="default" no-body="true">
 ^ Requirement      ^ Comment        ^ Requirement      ^ Comment       
 | Interpreting PHP scripts    | We want the web server to call the PHP interpreter when a page with the .php extension is requested.  | | Interpreting PHP scripts    | We want the web server to call the PHP interpreter when a page with the .php extension is requested.  |
-Access MySQL functions from PHP | Since we are setting up a LEMP server, we need to install a MySQL server and access it from PHP. We will install MariaDB, which is a direct replacement for MySQL. | +Accessing MySQL functions from PHP | Since we are setting up a LEMP server, we need to install a MySQL server and access it from PHP. We will install MariaDB, which is a direct replacement for MySQL. | 
-| Change the expiration date of HTTP headers to encourage caching. | We want files that do not change (e.g. CSS or images) to be cached on the client side to make the client experience more pleasant | +| Change the expiration date of the HTTP headers to encourage caching. | We want files that do not change (e.g. CSS or images) to be cached on the client side to make the experience more pleasant for the client 
-| Compress the text before it is served to the client. | We can compress the text that flows between the client and the server and in this way reduce the number of bytes transmitted over the wire, which in turn should provide a more pleasant experience for the client |+| Compress the text before it is sent to the client. | We can compress the text that flows between the client and the server and in this way reduce the number of bytes transmitted over the wire, which in turn should provide a more pleasant experience for the client |
 | Enable rewrite rules in CakePHP for pretty URLs | CakePHP uses the .htaccess files in Apache to enable pretty URLs. Since Nginx does not support .htaccess files, we need to modify Nginx to behave the same way. | | Enable rewrite rules in CakePHP for pretty URLs | CakePHP uses the .htaccess files in Apache to enable pretty URLs. Since Nginx does not support .htaccess files, we need to modify Nginx to behave the same way. |
  
Line 48: Line 52:
   * Please note that the behavior of the shell has changed in Ubuntu 22.04.   * Please note that the behavior of the shell has changed in Ubuntu 22.04.
   * It seems that it does NOT execute the multi-line insertion of commands.   * It seems that it does NOT execute the multi-line insertion of commands.
-  * So unfortunately you have to copy these commands line by line.+  * <wrap em>**So unfortunately you have to copy these commands line by line.**</wrap>
 </alert> </alert>
  
  
- +==== Adding a sudo user  ==== 
- +  * We assume that you have a clean installation of Ubuntu 22.04 WITHOUT Apache installed.
- +
-==== Add a sudo user  ==== +
-  * We assume that you have installed a clean installation of Ubuntu 22.04 WITHOUT Apache.+
   * If you have not yet added a sudo user add one now.   * If you have not yet added a sudo user add one now.
 <code bash> <code bash>
 # Add the system user # Add the system user
 sudo adduser system sudo adduser system
-# Update the system to the latest 
 sudo usermod -aG sudo system sudo usermod -aG sudo system
 +# Update the system to the latest 
 +sudo apt-get upgrade
 </code> </code>
  
 ==== Introduction to network technology under Ubuntu 22.04  ==== ==== Introduction to network technology under Ubuntu 22.04  ====
-  * If you do not yet have a working network configuration on the server on which you want to perform the installation, please use this section as a reference, otherwise simply continue with the next section. +  * If you do not yet have a working network configuration on the server on which you want to perform the installation, use this section as a reference, otherwise simply continue with the next section. 
-  * Since there is a big difference between Ubuntu 16.04 and Ubuntu 22.04, we feel that this section will help those who need to get used to the new way of working.+  * Since there is a big difference between Ubuntu 16.04 and Ubuntu 22.04, we believe this section will help those who need to get used to the new way of working.
   * We assume that you have a bare VM (like the one from https://www.osboxes.org/ubuntu-server/ )   * We assume that you have a bare VM (like the one from https://www.osboxes.org/ubuntu-server/ )
   * We also assume that you have used it to create a VM in Virtualbox and now only see the local loopback interface (127.0.0.1) when you enter the ip a command.   * We also assume that you have used it to create a VM in Virtualbox and now only see the local loopback interface (127.0.0.1) when you enter the ip a command.
-  *  To see which interfaces are available (although some may not yet be configured)+  *  To see which interfaces are available (even if some are not yet configured)
 <code bash> <code bash>
 ip a ip a
  </code>  </code>
-  * On my system it lists three since I plan to use the VM also as a router with Coova Chilli running on the one interface. So we have **lo**, **enp0s3** and **enp0s8**. +  * On my systemthree interfaces are shown as I plan to use the VM as a router as well, with Coova Chili running on the one interface. So we have **lo**, **enp0s3** and **enp0s8**. 
-  * For now I will just configure both of those interfaces to be DHCP clients.+  * At the moment I will only configure these two interfaces as DHCP clients.
 <code bash> <code bash>
 sudo vi /etc/netplan/50-cloud-init.yaml sudo vi /etc/netplan/50-cloud-init.yaml
  </code>  </code>
-  * We edit the file to look like this (adapt to fit your system's interfaces)+  * We edit the file so that it looks like this (adapt it to the interfaces of your system)
 <code bash> <code bash>
-# This file is generated from information provided by +# This file is generated from the information provided by 
-# the datasource.  Changes to it will not persist across an instance. +# the data source.  Changes to it do not persist across an instance. 
-# To disable cloud-init's network configuration capabilities, write a file +# To disable the network configuration functions of cloud-init, write a file 
-# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:+# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following content:
 # network: {config: disabled} # network: {config: disabled}
 network: network:
Line 98: Line 100:
                     optional: true                     optional: true
 </code> </code>
-  * Apply the network configuration using command:+  * Apply the network configuration with the command:
 <code bash> <code bash>
 sudo netplan --debug apply sudo netplan --debug apply
 </code> </code>
-  * If all went well our VM will now have an IP Address (via DHCP) which we can use.+  * If everything went wellour VM now has an IP address (via DHCP) that we can use.
 <code bash> <code bash>
 ip addr ip addr
Line 123: Line 125:
        valid_lft forever preferred_lft forever        valid_lft forever preferred_lft forever
 </code> </code>
-  * Now that we have a working network setup on our machine we can continue.+  * Now that we have set up a working network on our computer, we can continue.
  
 ==== Install Nginx ==== ==== Install Nginx ====
-  * We assume you have a clean install of Ubuntu 22.04 **WITHOUT** Apache installed.+  * We assume that you have installed a clean installation of Ubuntu 22.04 WITHOUT Apache.
  
  
Line 137: Line 139:
 </alert> </alert>
  
-  * Make sure it is up to date.+  * Make sure that it is up to date.
 <code bash> <code bash>
 # Get the latest package lists # Get the latest package lists
Line 144: Line 146:
 sudo apt-get upgrade sudo apt-get upgrade
 </code> </code>
-  * Ensure the English language pack is installed+  * Make sure that the English language pack is installed
 <code bash> <code bash>
 sudo apt-get -y install language-pack-en-base sudo apt-get -y install language-pack-en-base
Line 152: Line 154:
 sudo apt-get -y install nginx sudo apt-get -y install nginx
 </code> </code>
-  * Ensure the web server starts up and is running+  * Make sure that the web server is started and running
 <code bash> <code bash>
 sudo systemctl stop nginx.service sudo systemctl stop nginx.service
 sudo systemctl start nginx.service sudo systemctl start nginx.service
 </code> </code>
-  * Navigate to the IP Address of the server where you installed **Nginx** using a browser to ensure Nginx serves content e.g. http://127.0.0.1+  * Using a browser, navigate to the IP address of the server on which you have installed Nginx to ensure that Nginx is providing contente.g. http://127.0.0.1
    
 ==== Configure Nginx to interpret .php files ==== ==== Configure Nginx to interpret .php files ====
Line 171: Line 173:
 </code> </code>
  
-==== Modify Nginx ==== +==== Change Nginx ==== 
-  * Now that the php-fpm service is installed, let'modify the default Nginx server to use it.+  * Now that the php-fpm service is installed, we need to modify the default Nginx server to use it.
   * Edit the default server file:   * Edit the default server file:
 <code bash> <code bash>
Line 184: Line 186:
   * Enable PHP processing by leaving this section uncommented. Note that we are using the UNIX socket and that we are using 8.1 and not 7.4, which was originally specified in the configuration file.   * Enable PHP processing by leaving this section uncommented. Note that we are using the UNIX socket and that we are using 8.1 and not 7.4, which was originally specified in the configuration file.
 <code bash> <code bash>
-pass PHP scripts to FastCGI server+Pass PHP scripts to FastCGI server
 # #
 location ~ \.php$ { location ~ \.php$ {
Line 208: Line 210:
 sudo systemctl reload nginx.service sudo systemctl reload nginx.service
 </code> </code>
-  * Create a test //.php// file to confirm that it does work+  * Create a test //.php// file to confirm that it works.
 <code bash> <code bash>
 sudo vi /var/www/html/test.php sudo vi /var/www/html/test.php
 </code> </code>
-  * Contents:+  * Content:
 <code bash> <code bash>
 <?php <?php
Line 223: Line 225:
 ==== Install MariaDB ==== ==== Install MariaDB ====
 === Why MariaDB? === === Why MariaDB? ===
-  * We have found that the version of MySQL that is delivered by default with Ubuntu 22.04 causes problems with RADIUSdesk.+  * We have found that the version of MySQL that is comes by default with Ubuntu 22.04 causes problems with RADIUSdesk.
   * For this reason, we have installed MariaDB as an alternative.   * For this reason, we have installed MariaDB as an alternative.
   * MariaDB is an open-source relational database management system that is often used as an alternative to MySQL as the database part of the popular LAMP stack (Linux, Apache, MySQL, PHP/Python/Perl).   * MariaDB is an open-source relational database management system that is often used as an alternative to MySQL as the database part of the popular LAMP stack (Linux, Apache, MySQL, PHP/Python/Perl).
-  * It is intended as a drop-in replacement for MySQL. +  * It is intended as an immediate replacement for MySQL. 
-  * Make sure to provide a root password for the MariaDB database when asked for it if you are security conscious, otherwise just press the ESC key.+  * Be sure to provide a root password for the MariaDB database when prompted if you are security conscious, otherwise just hit the ESC key. 
 <code bash> <code bash>
 sudo apt-get -y install mariadb-server php8.1-mysql sudo apt-get -y install mariadb-server php8.1-mysql
Line 235: Line 238:
 </code> </code>
  
-=== Disable strict mode === +=== Deactivate strict mode === 
-  * With Ubuntu 22.04, the bundled version of MariaDB is on version 10.3, which has introduced some strict modes that have some issues with the RADIUSdesk database implementation.+  * On Ubuntu 22.04, the bundled version of MariaDB is on version 10.3, which has introduced some strict modes that have some issues with the RADIUSdesk database implementation.
   * We will disable the strict SQL mode in MariaDB by creating a new file /etc/mysql/conf.d/disable_strict_mode.cnf   * We will disable the strict SQL mode in MariaDB by creating a new file /etc/mysql/conf.d/disable_strict_mode.cnf
 <code bash> <code bash>
Line 246: Line 249:
 sql_mode=IGNORE_SPACE,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION sql_mode=IGNORE_SPACE,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
 </code> </code>
-  * Save the file and restart the MySQL Server+=== Enable the Event Scheduler === 
 +  * MariaDB and MySQL has a built in Event Scheduler (like CRON for a database) which is disabled by default. 
 +  * We make use of this feature to automatically optimize some of the database tables. 
 +  * We will enable the Event Scheduler in MariaDB by creating a new file /etc/mysql/conf.d/enable_event_scheduler.cnf 
 +<code bash> 
 +sudo vi /etc/mysql/conf.d/enable_event_scheduler.cnf 
 +</code> 
 +  * Enter these two lines: 
 +<code bash> 
 +[mysqld] 
 +event_scheduler=on 
 +</code> 
 +  * Save the file
 +  *  Restart the MySQL server
 <code bash> <code bash>
 sudo systemctl restart mariadb sudo systemctl restart mariadb
 +</code>
 +  * You can confirm that it is now enabled by checking the following from the SQL terminal:
 +<code bash>
 +sudo mysql -u root 
 +MariaDB [(none)]> SHOW GLOBAL VARIABLES LIKE 'event_scheduler';
 ++-----------------+-------+
 +| Variable_name   | Value |
 ++-----------------+-------+
 +| event_scheduler | ON    |
 ++-----------------+-------+
 +1 row in set (0.001 sec)
 </code> </code>
  
 ----- -----
-==== Performance tune Nginx ==== +==== Performance tuning for Nginx ==== 
-=== Modify expiry date for certain files === +=== Change the expiry date for certain files === 
-  * Edit the ///etc/nginx/sites-available/default// file:+  * Edit the file ///etc/nginx/sites-available/default// file:
 <code bash> <code bash>
 sudo vi /etc/nginx/sites-available/default sudo vi /etc/nginx/sites-available/default
 </code> </code>
-  * Add the following inside the server section:+  * Add the following within the server section:
 <code bash> <code bash>
 location ~ ^/cake4/.+\.(jpg|jpeg|gif|png|ico|js|css)$ { location ~ ^/cake4/.+\.(jpg|jpeg|gif|png|ico|js|css)$ {
Line 268: Line 295:
 } }
 </code> </code>
-  * Add below only if you require backward compatibility (MESHdesk and APdesk).+  * Only add the following information if you require backward compatibility (MESHdesk and APdesk).
 <code bash> <code bash>
 location ~ ^/cake3/.+\.(jpg|jpeg|gif|png|ico|js|css)$ { location ~ ^/cake3/.+\.(jpg|jpeg|gif|png|ico|js|css)$ {
Line 289: Line 316:
   * RADIUSdesk consists of three components.   * RADIUSdesk consists of three components.
     * **rd** directory with its contents contains all the HTML and JavaScript code and is used as the presentation layer.     * **rd** directory with its contents contains all the HTML and JavaScript code and is used as the presentation layer.
-    * **cake4** is a CakePHPv4 application and can be considered the engine room. Here the data is processed before being presented by the presentation layer. +    * **cake4** is a CakePHPv4 application and can be considered the engine room. This is where the data is processed before it is displayed by the presentation layer. 
-    * **login** is a directory with various login pages which are centrally managed through the RADIUSdesk **Dynamic Login Pages** applet. +    * **login** is a directory with various login pages that are managed centrally via the **RADIUSdesk Dynamic Login Pages** applet. 
-  * Later we will create various symbolic links from locations inside the **rdcore** directory to locations inside the web server'document root directory.+  * Later we will create various symbolic links from locations within the **rdcore** directory to locations within the document root directory of the web server.
  
 === Required packages === === Required packages ===
-  * Make sure the following packages are installed.+  * Make sure that the following packages are installed.
 <code bash> <code bash>
 sudo apt-get -y install php-cli php-mysql php-gd php-curl php-xml php-mbstring php-intl php-sqlite3 git wget sudo apt-get -y install php-cli php-mysql php-gd php-curl php-xml php-mbstring php-intl php-sqlite3 git wget
Line 304: Line 331:
 sudo git clone https://github.com/RADIUSdesk/rdcore.git sudo git clone https://github.com/RADIUSdesk/rdcore.git
 </code> </code>
-  *  This will create an **rdcore** directory that contains some subfolders.+  *   This will create an **rdcore** directory containing some subfolders.
   * It is recommended that you also include the RD Mobile UI.   * It is recommended that you also include the RD Mobile UI.
   * Check out the **rd_mobile** git repository.   * Check out the **rd_mobile** git repository.
Line 312: Line 339:
 </code> </code>
  
-=== Create softlinks ===+=== Create soft links ===
   * We will create softlinks in the directory where Nginx provides the RADIUSdesk content.   * We will create softlinks in the directory where Nginx provides the RADIUSdesk content.
 <code bash> <code bash>
Line 328: Line 355:
  
 === Change ownership === === Change ownership ===
-  * Change the ownership of the following files to www-data so Nginx can make changes to the files/directories+  * Change the ownership of the following files to www-data so that Nginx can make changes to the files/directories
 <code bash> <code bash>
 sudo mkdir -p  /var/www/html/cake4/rd_cake/logs sudo mkdir -p  /var/www/html/cake4/rd_cake/logs
Line 343: Line 370:
 </code> </code>
  
-=== The Database ===+=== The database ===
   * Make sure that the time zone on the server is set to UTC   * Make sure that the time zone on the server is set to UTC
   * Fill the time zone data in the DB   * Fill the time zone data in the DB
 <code bash> <code bash>
-#NOTE FAILING THIS STEP will break the RADIUS graphs +#NOTE FAILING TO DO THIS STEP will break the RADIUS graphs 
-#There might be some error messages in the output which is fine - no need to be alarmed+#Some error messages may appear in the outputwhich is not a problem - no need to worry
 sudo su sudo su
 mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root  mysql mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root  mysql
Line 369: Line 396:
 <alert type="warning"> <alert type="warning">
   * RADIUSdesk is under active development and sometimes we add SQL patches.   * RADIUSdesk is under active development and sometimes we add SQL patches.
-  * The SQL patches are located at **/var/www/html/cake4/rd_cake/setup/db/**.+  * The SQL patches are located under **/var/www/html/cake4/rd_cake/setup/db/**.
   * These patches are non-destructive and you can run them against the database   * These patches are non-destructive and you can run them against the database
-  * See the sample below+  * See the example below
 <code bash> <code bash>
 sudo mysql -u root rd < /var/www/rdcore/cake4/rd_cake/setup/db/8.068_add_email_sms_histories.sql  sudo mysql -u root rd < /var/www/rdcore/cake4/rd_cake/setup/db/8.068_add_email_sms_histories.sql 
 +</code>
 +  * Some of these patches may add new columns to existing database tables. In this case, it is recommended to clear the CakePHP models (tables) cache to ensure that the latest changes are also applied there:
 +<code bash>
 +sudo su
 +cd /var/www/rdcore/cake4/rd_cake/tmp/cache/models
 +rm *
 +exit
 </code> </code>
 </alert> </alert>
- 
  
 === Configure Nginx === === Configure Nginx ===
  
-  * Configure Nginx to rewrite some RdCore URLs starting with ///cake4/rd_cake//.+  * Configure Nginx to rewrite some RdCore URLs that start with ///cake4/rd_cake//.
   * Edit ///etc/nginx/sites-enabled/default//   * Edit ///etc/nginx/sites-enabled/default//
 <code bash> <code bash>
 sudo vi /etc/nginx/sites-enabled/default sudo vi /etc/nginx/sites-enabled/default
 </code> </code>
-  * Add this once section directly below **server_name** item. (This is so that this rule is **hit** first for the reporting side. We do not use CakePHP for the reporting anymore due to performance issues.+  * Insert this section directly under the **server_name** entry. (This is so that this rule is **hit** first for the reporting side. Due to performance issues, we no longer use CakePHP for reporting.
 <code bash> <code bash>
 server_name _; server_name _;
Line 392: Line 425:
 } }
 </code> </code>
-  * If you need backward compatibility support (MESHdesk and APdesk) also add this section:+  * If you need support for backward compatibility (MESHdesk and APdesk)add this section as well:
 <code bash> <code bash>
 location /cake3/rd_cake/node-reports/submit_report.json { location /cake3/rd_cake/node-reports/submit_report.json {
Line 398: Line 431:
 } }
 </code> </code>
-  * Add the following configuration block inside the server section (This you can add towards the end):+  * Insert the following configuration block into the server section (you can add this towards the end):
 <code bash> <code bash>
 location /cake4/rd_cake { location /cake4/rd_cake {
Line 405: Line 438:
 } }
 </code> </code>
-  * If you need backward compatibility support (MESHdesk and APdesk) also add this section:+  *  If you need support for backward compatibility (MESHdesk and APdesk)add this section as well:
 <code bash> <code bash>
 location /cake3/rd_cake { location /cake3/rd_cake {
Line 418: Line 451:
  
 === Important URLs ===   === Important URLs ===  
-  * The following URLs are important to reach the UI +  * The following URLs are important to reach the user interface 
-  * To load the optimized UI, go to http://127.0.0.1/rd/build/production/Rd/ +  * To load the optimized user interface, go to http://127.0.0.1/rd/build/production/Rd/ 
-  * If you want to serve the content directly out of the webroot, do the following:+  * If you want to deliver the content directly from the webroot, proceed as follows:
 <code bash> <code bash>
 sudo cp -R /var/www/html/rd/build/production/Rd/* /var/www/html/ sudo cp -R /var/www/html/rd/build/production/Rd/* /var/www/html/
Line 426: Line 459:
   * To load the RD Mobile UI, go to http://127.0.0.1/rd_mobile   * To load the RD Mobile UI, go to http://127.0.0.1/rd_mobile
  
-== Login Credentials == +== Login credentials == 
   * By default you can log in with the following credentials   * By default you can log in with the following credentials
 Username: **root** Password: **admin** Username: **root** Password: **admin**
Line 441: Line 474:
  
 ===== Add LETSENCRYPT certificate ===== ===== Add LETSENCRYPT certificate =====
-  * Instead of repeating the existing documentation, we simply add a URL with the appropriate instructions. +  * Instead of repeating the existing documentation, we simply add a URL with the corresponding instructions 
-  * You may want to do the following first before following the instructions in the URL +  * Before you follow the instructions in the URL, you should first do the following
 <code bash> <code bash>
 sudo apt-get update sudo apt-get update
Line 450: Line 482:
   * https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-22-04   * https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-22-04
 ===== Next steps ===== ===== Next steps =====
-  * Be sure to also install **FreeRADIUS** +  * Make sure that you also install **FreeRADIUS**. 
-  * [[Getting Started:22_install_ubuntu_freeradius_3|Install FreeRADIUS]]+  * [[install_22_4_freeradius|Install FreeRADIUS]]
  • install_22_4.1707318220.txt.gz
  • Last modified: 2024/02/07 17:03
  • by system