31.07.2024
Instalacja i konfiguracja strony internetowej na VPS z Ubuntu 22.04 LTS
Bazy danychKonfiguracjaLinux | UnixPrywatneWWW
strona-internetowa-na-ubuntu-2204-lts

Ostatnia aktualizacja: 27.01.2025 r.

Przez prawie 3 lata moja strona bez zarzutów działała na Ubuntu Server 20.04 LTS. Firma Canonical 25 kwietnia 2024 roku wydała stabilną wersją Ubuntu Server 24.04 LTS i stwierdziłem, że jest to dobry moment, aby ustawić wszystko od zera na Ubuntu Server 22.04 LTS. 😜 Powodów tej decyzji było kilka:

  1. upgrade systemu do wersji 22.04 LTS generował masę błędów,
  2. konieczność przejścia z PHP 7.4 na 8.3,
  3. poprawienie działania strony głównej (powiązane z pkt. 2),
  4. aktualizacja systemu BookStack pod subdomeną zycie.grzegorzwita.it do najnowszej dostępnej wersji (powiązane z pkt. 2),
  5. instalacja dodatkowych systemów (powiązane z pkt. 2),
  6. aktualizacja parametrów VPS pod zmiany w ofercie.

Generalnie całość byłbym wstanie wykonać na Ubuntu 20.04 LTS, ale wolałem to już zrobić na nowszej wersji systemu. Pierwotnie na VPS działały dwie strony z dwoma dodatkowymi usługami dla agencji czyli phpmyadmin oraz FTP. W wersji "v2" postanowiłem postawić dodatkowe dwa systemy i jedną usługę, co w efekcie, mocno rozbudowało moją konfigurację:

  1. grzegorzwita.it - strona główna wraz z phpmyadmin i FTP,
  2. zycie.grzegorzwita.it - prywatny notatnik oparty o system BookStack,
  3. wiki.grzegorzwita.it - prywatny zbiór porad dla ekosystemu Microsoftu oparty o system Wiki.js,
  4. system.grzegorzwita.it - mały CRM oparty o system Invoice Ninja,
  5. grzegorzwita.it\statystyka - alias do pliku statystyk Apache`a oparty o system GoAccess (oparty o wersję z repozytorium Ubuntu, a nie z GitHub`a projektu).

Ustawienie tego wszystkiego, aby działało razem, zajęło mi trochę czasu i po drodze napotkałem kilka problemów - rozwiązanie niektórych zajęło mi parę dni jak np. ustawienie Wiki.js do działania poza Docker`em i dlaczego Wiki.js przestaje być dostępne po instalacji Invoice Ninja. 😂 Finalnie uporałem się z wszystkimi napotkanymi błędami i póki co działa to wszystko bardzo dobrze. 😎

//Parametry VPS i wstępne przygotowanie systemu

Parametry sprzętowe w "v2" uległy polepszeniu - zamiast 1 rdzenia Intel Xeon serii Skylake są 2 rdzenie AMD EPYC 7002 (prawdopodobnie AMD EPYC 7H12 (830F10)) oraz podwojeniu uległa przestrzeń dyskowa. Obecne parametry to:

  • 2 rdzenie
  • 2 GB RAM
  • 40 GB NVMe SSD

Wynik testy YABS`a:

# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
#              Yet-Another-Bench-Script              #
#                     v2024-06-09                    #
# https://github.com/masonr/yet-another-bench-script #
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## #

Tue Dec  3 05:45:32 PM CET 2024

Basic System Information:
---------------------------------
Uptime     : 8 days, 48 hours, 0 minutes
Processor  : AMD EPYC Processor
CPU cores  : 2 @ 2495.312 MHz
AES-NI     : ✔ Enabled
VM-x/AMD-V : ❌ Disabled
RAM        : 1.9 GiB
Swap       : 0.0 KiB
Disk       : 37.5 GiB
Distro     : Ubuntu 22.04.5 LTS
Kernel     : 5.15.0-126-generic
VM Type    : KVM
IPv4/IPv6  : ✔ Online / ✔ Online

IPv6 Network Information:
---------------------------------
ISP        : Hetzner Online GmbH
ASN        : AS24940 Hetzner Online GmbH
Host       : Hetzner Online GmbH
Location   : Helsinki, Uusimaa (18)
Country    : Finland

fio Disk Speed Tests (Mixed R/W 50/50) (Partition /dev/sda1):
---------------------------------
Block Size | 4k            (IOPS) | 64k           (IOPS)
  ------   | ---            ----  | ----           ----
Read       | 110.23 MB/s  (27.5k) | 1.16 GB/s    (18.2k)
Write      | 110.52 MB/s  (27.6k) | 1.17 GB/s    (18.3k)
Total      | 220.76 MB/s  (55.1k) | 2.34 GB/s    (36.5k)
           |                      |
Block Size | 512k          (IOPS) | 1m            (IOPS)
  ------   | ---            ----  | ----           ----
Read       | 1.18 GB/s     (2.3k) | 1.27 GB/s     (1.2k)
Write      | 1.24 GB/s     (2.4k) | 1.35 GB/s     (1.3k)
Total      | 2.42 GB/s     (4.7k) | 2.62 GB/s     (2.5k)

iperf3 Network Speed Tests (IPv4):
---------------------------------
Provider        | Location (Link)           | Send Speed      | Recv Speed      | Ping
-----           | -----                     | ----            | ----            | ----
Clouvider       | London, UK (10G)          | 1.07 Gbits/sec  | 5.18 Gbits/sec  | 38.4 ms
Eranium         | Amsterdam, NL (100G)      | 7.80 Gbits/sec  | 7.10 Gbits/sec  | 29.7 ms
Uztelecom       | Tashkent, UZ (10G)        | 1.07 Gbits/sec  | busy            | 61.0 ms
Leaseweb        | Singapore, SG (10G)       | 188 Mbits/sec   | 987 Mbits/sec   | 179 ms
Clouvider       | Los Angeles, CA, US (10G) | 987 Mbits/sec   | 1.06 Gbits/sec  | 157 ms
Leaseweb        | NYC, NY, US (10G)         | 1.25 Gbits/sec  | 1.91 Gbits/sec  | 96.2 ms
Edgoo           | Sao Paulo, BR (1G)        | 600 Mbits/sec   | 780 Mbits/sec   | 218 ms

iperf3 Network Speed Tests (IPv6):
---------------------------------
Provider        | Location (Link)           | Send Speed      | Recv Speed      | Ping
-----           | -----                     | ----            | ----            | ----
Clouvider       | London, UK (10G)          | 3.04 Gbits/sec  | 5.10 Gbits/sec  | 37.2 ms
Eranium         | Amsterdam, NL (100G)      | 7.68 Gbits/sec  | 7.09 Gbits/sec  | 28.0 ms
Uztelecom       | Tashkent, UZ (10G)        | busy            | 293 Mbits/sec   | 60.9 ms
Leaseweb        | Singapore, SG (10G)       | 870 Mbits/sec   | 978 Mbits/sec   | 179 ms
Clouvider       | Los Angeles, CA, US (10G) | 854 Mbits/sec   | 1.13 Gbits/sec  | 157 ms
Leaseweb        | NYC, NY, US (10G)         | 1.17 Gbits/sec  | busy            | 96.2 ms
Edgoo           | Sao Paulo, BR (1G)        | 818 Mbits/sec   | 789 Mbits/sec   | 216 ms

Geekbench 6 test failed. Run manually to determine cause.

YABS completed in 10 min 35 sec

Loguję się na VPS na konto root za pomocą wygenerowanego hasła, które od razu zmieniam na swoje własne. Następnie tworzę konto dla siebie i dodaję je do grupy sudo.

adduser nazwa_użytkownika
usermod -aG sudo nazwa_użytkownika

Przelogowuję się na swoje konto, a następnie:

  • aktualizuję system i pakiety do najnowszych dostępnych wersji,
    sudo apt-get update && sudo apt-get upgrade -y && sudo apt-get dist-upgrade -y && sudo apt-get autoremove -y
  • ustawiam odpowiednią strefę czasową,
    sudo dpkg-reconfigure tzdata
  • instaluję dodatkowe oprogramowanie.
    sudo apt-get install apt-transport-https unzip -y
    sudo wget https://7-zip.org/a/7z2407-linux-x64.tar.xz && sudo tar -xf 7z2407-linux-x64.tar.xz -C /usr/bin/ 7zz && sudo rm 7z2407-linux-x64.tar.xz

//SSH

  1. Przygotowuję klucz z hasłem.
    ssh-keygen -t ed25519 -o -a 100
  2. Przygotowuję katalog dla klucza.
    touch .ssh/authorized_keys
  3. Kopiuję klucz publiczny do authorized_keys, a następnie pobieram klucz prywatny na swój komputer np. za pomocą WinSCP.
    cat .ssh/id_ed25519.pub >> .ssh/authorized_keys
  4. Usuwam wygenerowane pliki klucza SSH.
    rm .ssh/id_ed25519*
  5. Ustawiam odpowiednie uprawnienia dla pliku authorized_keys.
    chmod 600 .ssh/authorized_keys
  6. Aktualizuję konfigurację SSH i modyfikuję poniższe pozycje.
    sudo nano /etc/ssh/sshd_config
    [...]
    #Include /etc/ssh/sshd_config.d/*.conf
    [...]
    Port numer_portu
    [...]
    PermitRootLogin no
    [...]
    PubkeyAuthentication yes
    [...]
    AuthorizedKeysFile .ssh/authorized_keys
    [...]
    PasswordAuthentication no
    PermitEmptyPasswords no
    [...]
    ClientAliveInterval 300
    ClientAliveCountMax 3
    [...]
    
  7. Włączam zaporę sieciową w systemie.
    sudo ufw enable
  8. Udostępniam port SSH na zaporze sieciowej.
    sudo ufw allow from any to any port numer_portu proto tcp
  9. Restartuję usługę SSH.
    sudo systemctl restart ssh

//Apache

  1. Dodaję repozytorium PPA dla PHP.
    LC_ALL=C.UTF-8 sudo add-apt-repository ppa:ondrej/php
  2. Instaluję PHP 8.3.
    sudo apt-get install php8.3 -y
  3. Instaluję dodatkowe rozszerzenia dla PHP 8.3.
    sudo apt-get install php8.3-{mysql,fpm,curl,mbstring,ldap,xml,zip,gd,gmp,tidy,imagick,bcmath,bz2,intl,soap,xmlrpc} -y
  4. Tworzę katalog dla plików strony internetowej.
    sudo mkdir /var/www/grzegorzwitait
  5. Przenoszę pliki strony internetowej do utworzonego folderu.
    sudo mv -f /home/nazwa_użytkownika/PLIKI/grzegorzwitait/{.,}* /var/www/grzegorzwitait/
  6. Ustawiam rekurencyjnie uprawnienia dla katalogów i plików dla użytkownika i grupy www-data.
    sudo chown -R www-data:www-data /var/www/grzegorzwitait/
  7. Ustawiam uprawnienia 755 dla wszystkich katalogów oraz 644 dla wszystkich plików.
    sudo find /var/www/grzegorzwitait/ -type d -exec chmod 755 {} \;
    sudo find /var/www/grzegorzwitait/ -type f -exec chmod 644 {} \;
  8. Ustawiam uprawnienia 775 dla wszystkich katalogów oraz 664 dla wszystkich plików w lokalizacjach do których dodawane są zdjęcia i pliki.
    sudo find /var/www/grzegorzwitait/files/page_files/* -type d -exec chmod 775 {} \;
    sudo find /var/www/grzegorzwitait/files/page_files/* -type f -exec chmod 664 {} \;
    sudo find /var/www/grzegorzwitait/images/page_images/foto_* -type d -exec chmod 775 {} \;
    sudo find /var/www/grzegorzwitait/images/page_images/foto_* -type f -exec chmod 664 {} \;
  9. Aktualizuję dostępy do bazy danych w pliku konfiguracyjnym oraz ustawiam uprawnienie 740 dla tego pliku.
    sudo nano /var/www/grzegorzwitait/database.php
    sudo chmod 740 /var/www/grzegorzwitait/database.php
  10. Zmieniam właściciela na root oraz grupę na www-data dla katalogu nadrzędnego.
    sudo chown root:www-data /var/www/grzegorzwitait/
  11. Ustawiam konfigurację strony.
    sudo nano /etc/apache2/sites-available/grzegorzwitait.conf
    <VirtualHost *:80>
        ServerName grzegorzwita.it
        ServerAdmin admin@grzegorzwita.it
        
        RewriteEngine On
        RewriteCond %{HTTP:X-Forwarded-Proto} !https [NC]
        RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,QSA,R=permanent]
    </VirtualHost>
    
    <IfModule mod_ssl.c>
    SSLStaplingCache "shmcb:/var/log/ssl_stapling(150000)"
    <VirtualHost *:443>
        Protocols h2 http/1.1
        ServerName grzegorzwita.it
        ServerAdmin admin@grzegorzwita.it
    
        DocumentRoot /var/www/grzegorzwitait/
        DirectoryIndex index.php
    
        Redirect permanent /statystyka https://grzegorzwita.it/statystyka.html
    
        <Directory /var/www/grzegorzwitait/>
            Options -Indexes -Includes +FollowSymLinks +MultiViews
    	    AllowOverride all
    	    Require all granted
        </Directory>
        
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
    
        Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        Header always set X-Frame-Options "SAMEORIGIN"
        Header always set X-XSS-Protection "1; mode=block"
        Header always set X-Content-Type-Options "nosniff"
        Header always set Referrer-Policy "strict-origin-when-cross-origin"
        Header always set Content-Security-Policy "form-action 'self'; base-uri 'self'; frame-ancestors 'self'; object-src 'none'; worker-src 'self'; child-src 'self'; frame-src 'self'; upgrade-insecure-requests"
    
        SSLEngine on
        SSLProtocol -all +TLSv1.2 +TLSv1.3
        SSLCipherSuite EECDH+AESGCM:EDH+AESGCM
        SSLOpenSSLConfCmd Curves X25519:secp521r1:secp384r1:prime256v1
        SSLOpenSSLConfCmd Options -SessionTicket,ServerPreference    
        SSLHonorCipherOrder off
        SSLSessionTickets off
        SSLCompression off
        SSLUseStapling on
        SSLCertificateFile /etc/letsencrypt/live/grzegorzwita.it/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/grzegorzwita.it/privkey.pem
    </VirtualHost>
    </IfModule>
  12. Ustawiam uprawnienia root:root dla pliku konfiguracyjnego strony.
    sudo chown root:root /etc/apache2/sites-available/grzegorzwitait.conf
  13. Włączam konfigurację strony.
    sudo a2ensite grzegorzwitait.conf
  14. Wyłączam konfigurację domyślnej strony Apache`a.
    sudo a2dissite 000-default.conf
  15. Wyłączam niepotrzebne moduły PHP.
    sudo a2dismod php8.3 mpm_prefork
  16. Włączam potrzebne moduły PHP.
    sudo a2enmod rewrite headers http2 mpm_event proxy_fcgi proxy_http ssl
  17. Włączam konfigurację PHP-FPM.
    sudo a2enconf php8.3-fpm
  18. Zmieniam ustawienia PHP-FPM.
    sudo sed -i "s/;date.timezone =/date.timezone = Europe\/Warsaw/" /etc/php/8.3/fpm/php.ini
    sudo sed -i "s/memory_limit = 128M/memory_limit = 1024M/" /etc/php/8.3/fpm/php.ini
    sudo sed -i "s/upload_max_filesize = 2M/upload_max_filesize = 6M/" /etc/php/8.3/fpm/php.ini
    sudo sed -i "s/max_execution_time = 30/max_execution_time = 60/" /etc/php/8.3/fpm/php.ini
    sudo sed -i "s/post_max_size = 8M/post_max_size = 16M/" /etc/php/8.3/fpm/php.ini
    sudo sed -i "s/max_file_uploads = 20/max_file_uploads = 40/" /etc/php/8.3/fpm/php.ini
  19. Restartuję usługę PHP-FPM.
    sudo systemctl restart php8.3-fpm.service
  20. Udostępniam porty Apache`a w zaporze sieciowej.
    sudo ufw allow from any to any port 80,443 proto tcp

//MySQL

  1. Instaluję serwer MySQL.
    sudo apt-get install mysql-server -y
  2. Uruchamiam konfigurator serwera MySQL.
    sudo mysql_secure_installation
  3. Loguję się do serwera MySQL.
    sudo mysql -u root -p
  4. Tworzę bazę danych dla strony internetowej.
    CREATE DATABASE grzegorzwitait_dba;
  5. Tworzę użytkownika do bazy danych dla strony internetowej.
    CREATE USER 'grzegorzwitait_dba'@'localhost' IDENTIFIED WITH caching_sha2_password BY '8arDzo_Sk0mp1ikow4N3_Ha$LO!';
  6. Nadaję odpowiednie uprawnienia utworzonemu użytkownikowi.
    GRANT ALL ON grzegorzwitait_dba.* TO 'grzegorzwitait_dba'@'localhost';
  7. Wprowadzam zmiany w życie.
    FLUSH PRIVILEGES;
  8. Wychodzę z serwera bazy danych.
    EXIT
  9. Importuję bazę danych z kopii zapasowej.
    sudo mysql -u root -p grzegorzwitait_dba < /home/nazwa_użytkownika/PLIKI/grzegorzwitait_*.sql

//SSL

  1. Instaluję odpowiednie pakiety.
    sudo apt-get install certbot python3-certbot-apache -y
  2. Generuję certyfikat Wildcard i postępuję zgodnie z informacjami wyświetlanymi na ekranie.
    sudo certbot certonly --manual --preferred-challenges=dns --email admin@grzegorzwita.it --server https://acme-v02.api.letsencrypt.org/directory --agree-tos -d "*.grzegorzwita.it, grzegorzwita.it"
  3. Sprawdzam certyfikaty.
    sudo certbot certificates
  4. Przygotowuję skrypt, który będę wykorzystywał przy odświeżaniu certyfikatu oraz ustawiam uprawnienie 740, abym mógł go uruchamiać.
    sudo nano /root/letsencrypt_renew.sh
    #!/bin/bash
    sudo certbot certonly --manual --preferred-challenges=dns --email admin@grzegorzwita.it --server https://acme-v02.api.letsencrypt.org/directory --agree-tos -d "*.grzegorzwita.it, grzegorzwita.it"
    sudo systemctl reload apache2
    sudo chmod 740 /root/letsencrypt_renew.sh
  5. Sprawdzam poprawność konfiguracji Apache`a.
    sudo apache2ctl configtest
  6. Restartuję usługę Apache`a.
    sudo systemctl restart apache2
  7. Weryfikuję zabezpieczenia strony na https://www.ssllabs.com/ssltest/.

//phpmyadmin

  1. Loguję się do serwera MySQL.
    sudo mysql -u root -p
  2. Tworzę bazę danych dla phpmyadmin.
    CREATE DATABASE grzegorzwitait_pma;
  3. Tworzę użytkownika do bazy danych dla phpmyadmin.
    CREATE USER 'grzegorzwitait_pma'@'localhost' IDENTIFIED WITH caching_sha2_password BY '8arDzo_Sk0mp1ikow4N3_Ha$LO!';
  4. Nadaję odpowiednie uprawnienia utworzonemu użytkownikowi dla bazy danych phpmyadmin oraz strony internetowej.
    GRANT ALL ON grzegorzwitait_pma.* TO 'grzegorzwitait_pma'@'localhost';
    GRANT ALL ON grzegorzwitait_dba.* TO 'grzegorzwitait_pma'@'localhost';
  5. Wprowadzam zmiany w życie.
    FLUSH PRIVILEGES;
  6. Tymczasowo usuwam komponent bazy danych.
    UNINSTALL COMPONENT "file://component_validate_password";
  7. Wychodzę z serwera bazy danych.
    EXIT
  8. Instaluję pakiet phpmyadmin ale nie tworzę bazy danych za pomocą narzędzia dbconfig-common.
    sudo apt-get install phpmyadmin -y
  9. Ponownie loguję się do serwera bazy danych MySQL.
    sudo mysql -u root -p
  10. Przywracam wcześniej usunięty komponent bazy danych.
    INSTALL COMPONENT "file://component_validate_password";
  11. Wychodzę z serwera bazy danych.
    EXIT
  12. Aktualizuję konfigurację phpmyadmin.
    sudo nano /etc/phpmyadmin/config.inc.php
    [...]
    /* User for advanced features */
    $cfg['Servers'][$i]['controluser'] = 'grzegorzwitait_pma';
    $cfg['Servers'][$i]['controlpass'] = '8arDzo_Sk0mp1ikow4N3_Ha$LO!';
    [...]
  13. Aktualizuję konfigurację Apache`a.
    sudo nano /etc/apache2/conf-available/phpmyadmin.conf
    <Directory /usr/share/phpmyadmin>
        [. . .]
        AllowOverride All
    
        [. . .]
    </Directory>
  14. Włączam moduł PHP.
    sudo phpenmod mbstring
  15. Restartuję usługę Apache`a.
    sudo systemctl restart apache2
  16. W przeglądarce internetowej wchodzę na adres grzegorzwita.it/phpmyadmin i loguję się danymi wprowadzonymi podczas konfiguracji. Po poprawnym zalogowaniu się zaznaczam odpowiednią bazę danych, a następnie w menu u samej góry klikam w Opcje.

  17. W kolejnym kroku klikam w odnośnie Utwórz...

    ...i dosłownie po niespełna sekundzie baza danych zostaje przygotowana.

//FTP

  1. Instaluję pakiet vsftpd.
    sudo apt-get install vsftpd -y
  2. Udostępniam na zaporze sieciowej porty 20, 21 oraz zakres portów od 40 000 do 50 000.
    sudo ufw delete allow from any to any port 20:21,40000:50000 proto tcp comment 'FTP'
  3. Aktualizuję konfigurację FTP.
    sudo nano /etc/vsftpd.conf
    [...]
    listen=YES
    [...]
    listen_ipv6=NO
    [...]
    write_enable=YES
    [...]
    local_umask=022
    [...]
    chroot_local_user=YES
    [...]
    
    allow_writeable_chroot=YES
    force_dot_files=YES
    pasv_min_port=40000
    pasv_max_port=50000
  4. Restartuję usługę FTP.
    sudo systemctl restart vsftpd.service
  5. Sprawdzam status działania usługi FTP.
    sudo systemctl status vsftpd.service
  6. Tworzę dedykowane konto FTP wraz z lokalizacją, która będzie dla niego widoczna.
    sudo adduser --home /var/www/grzegorzwitait/ --ingroup www-data nazwa_uzytkownika
  7. Uprawnienia na potrzeby pracy na FTP.
    sudo find /var/www/grzegorzwitait/ -type d -exec chmod 775 {} \;
    sudo find /var/www/grzegorzwitait/ -type f -exec chmod 664 {} \;

//BookStack

  1. Instaluję pakiet composer.
    sudo apt-get install composer -y
  2. Tworzę katalog na potrzeby Bookstack.
    sudo mkdir /var/www/BookStack
  3. Przenoszę pliki kopii zapasowej.
    sudo mv -f /home/grzegorz_wita/PLIKI/BookStack/{.,}* /var/www/BookStack/
  4. Ustawiam rekurencyjnie uprawnienia plików i katalogów na użytkownika i grupę www-data.
    sudo chown -R www-data:www-data /var/www/BookStack/
  5. Ustawiam uprawnienia katalogów na 755, a plików na 644.
    sudo find /var/www/BookStack/ -type d -exec chmod 755 {} \;
    sudo find /var/www/BookStack/ -type f -exec chmod 644 {} \;
  6. Aktualizuję plik konfiguracyjny.
    sudo nano /var/www/BookStack/.env
  7. Ustawiam uprawnienia pliku konfiguracyjnego na 740.
    sudo chmod 740 /var/www/BookStack/.env
  8. Ustawiam uprawnienia plików na 775 w trzech lokalizacjach.
    sudo chmod 775 /var/www/BookStack/bootstrap/cache/ /var/www/BookStack/public/uploads/ /var/www/BookStack/storage/
  9. Zmieniam właściciela i grupę na root dla katalogu nadrzędnego.
    sudo chown root:root /var/www/BookStack/
  10. Ustawiam rekurencyjnie właściciela i grupę na root dla katalogów i plików w katalogach repozytorium.
    sudo chown -R root:root /var/www/BookStack/.git
    sudo chown -R root:root /var/www/BookStack/.github
  11. Loguję się do serwera MySQL.
    sudo mysql -u root -p
  12. Tworzę bazę danych dla Bookstack.
    CREATE DATABASE bookstack;
  13. Tworzę użytkownika do bazy danych dla Bookstack.
    CREATE USER 'bookstack_dba'@'localhost' IDENTIFIED WITH caching_sha2_password BY '8arDzo_Sk0mp1ikow4N3_Ha$LO!';
  14. Nadaję odpowiednie uprawnienia utworzonemu użytkownikowi.
    GRANT ALL ON bookstack.* TO 'bookstack_dba'@'localhost';
  15. Wprowadzam zmiany w życie.
    FLUSH PRIVILEGES;
  16. Wychodzę z serwera bazy danych.
    EXIT
  17. Importuję bazę danych z kopii zapasowej.
    sudo mysql -u root -p bookstack < /home/grzegorz_wita/PLIKI/grzegorzwitait_*.sql
  18. Przechodzę do katalogu Bookstack`a.
    cd /var/www/BookStack/
  19. Resetuję git`a.
    sudo git reset --hard HEAD
  20. Pobieram aktualną wersję programu z repozytorium Github`a.
    sudo git pull origin release
  21. Instaluję zależności composer`a.
    sudo composer install --no-dev --no-plugins
  22. Aktualizuję bazę danych oraz wykonuję czyszczenie.
    sudo php artisan migrate && sudo php artisan cache:clear && sudo php artisan config:clear && sudo php artisan view:clear
  23. Tworzę konfigurację strony dla Apache`a.
    sudo nano /etc/apache2/sites-available/bookstack.conf
    <VirtualHost *:80>
        ServerName zycie.grzegorzwita.it
        ServerAdmin admin@grzegorzwita.it
        Redirect / https://zycie.grzegorzwita.it
    </VirtualHost>
    
    <VirtualHost *:443>
        ServerName zycie.grzegorzwita.it
        ServerAdmin admin@grzegorzwita.it
    
        DocumentRoot /var/www/BookStack/public/
    
        <Directory /var/www/BookStack/public/>
            Options Indexes FollowSymLinks
            AllowOverride None
            Require all granted
            <IfModule mod_rewrite.c>
                <IfModule mod_negotiation.c>
                    Options -MultiViews -Indexes
                </IfModule>
                RewriteEngine On
                # Handle Authorization Header
                RewriteCond %{HTTP:Authorization} .
                RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
                # Redirect Trailing Slashes If Not A Folder...
                RewriteCond %{REQUEST_FILENAME} !-d
                RewriteCond %{REQUEST_URI} (.+)/$
                RewriteRule ^ %1 [L,R=301]
                # Handle Front Controller...
                RewriteCond %{REQUEST_FILENAME} !-d
                RewriteCond %{REQUEST_FILENAME} !-f
                RewriteRule ^ index.php [L]
            </IfModule>
        </Directory>
    
        ErrorLog ${APACHE_LOG_DIR}/error_bookstack.log
        CustomLog ${APACHE_LOG_DIR}/access_bookstack.log combined
    
        SSLEngine on
        SSLCertificateFile /etc/letsencrypt/live/grzegorzwita.it/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/grzegorzwita.it/privkey.pem
    </VirtualHost>
  24. Włączam konfigurację strony i restartuję usługę Apache`a.
    sudo a2ensite bookstack.conf
  25. BookStack`a w przyszłości aktualizuję w poniższy sposób.
    cd /var/www/BookStack/ && sudo git pull origin release && sudo composer install --no-dev && sudo php artisan migrate && sudo php artisan cache:clear && sudo php artisan config:clear && sudo php artisan view:clear

//Wiki.js

  1. Dodaję repozytorium dla node.js w wersji 22.
    sudo curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
  2. Instaluję pakiet nodejs.
    sudo apt-get install nodejs -y
  3. Tworzę katalog dla Wiki.js.
    sudo mkdir /var/www/Wikijs
  4. Pobieram najnowszą dostępną wersję Wiki.js z repozytorium.
    sudo wget https://github.com/Requarks/wiki/releases/latest/download/wiki-js.tar.gz
  5. Rozpakowuję pobrane archiwum.
    sudo tar xzf wiki-js.tar.gz
  6. Usuwam pobrany plik archiwum.
    sudo rm wiki-js.tar.gz
  7. Loguję się do serwera MySQL.
    sudo mysql -u root -p
  8. Tworzę bazę danych dla Wiki.js.
    CREATE DATABASE wikijs;
  9. Tworzę użytkownika do bazy danych dla Wiki.js.
    CREATE USER 'wikijs_dba'@'localhost' IDENTIFIED WITH caching_sha2_password BY '8arDzo_Sk0mp1ikow4N3_Ha$LO!';
  10. Nadaję odpowiednie uprawnienia utworzonemu użytkownikowi.
    GRANT ALL ON wikijs.* TO 'wikijs_dba'@'localhost';
  11. Wprowadzam zmiany w życie.
    FLUSH PRIVILEGES;
  12. Wychodzę z serwera bazy danych.
    EXIT
  13. Przygotowuję plik konfiguracyjny.
    sudo cp config.sample.yml config.yml
  14. Ustawiam plik konfiguracyjny.
    sudo nano config.yml
    [...]
    db:
      type: mysql
    
      #PostreSQL / MySQL / MariaDB / MS SQL Server only:
      host: localhost
      port: 3306
      user: wikijs_dba
      pass: 8arDzo_Sk0mp1ikow4N3_Ha$LO!
      db: wikijs
      ssl: false
    
    [...]
  15. Ustawiam rekurencyjnie właściciela i grupę dla katalogów i plików www-data.
    sudo chown -R www-data:www-data /var/www/Wikijs/
  16. Ustawiam uprawnienia dla katalogów na 755, a plików na 644.
    sudo find /var/www/Wikijs/ -type d -exec chmod 755 {} \;
    sudo find /var/www/Wikijs/ -type f -exec chmod 644 {} \;
  17. Ustawiam uprawnienia na 740 dla pliku konfiguracyjnego.
    sudo chmod 740 /var/www/Wikijs/config.yml
  18. Ustawiam właściciela i grupę na root dla katalogu nadrzędnego.
    sudo chown root:root /var/www/Wikijs/
  19. Przygotowuję plik serwisu dla Wiki.js.
    sudo nano /etc/systemd/system/wikijs.service
    [Unit]
    Description=Wiki.js
    After=network.target
    
    [Service]
    Type=simple
    ExecStart=/usr/bin/node server
    Restart=always
    
    User=root
    Environment=NODE_ENV=production
    WorkingDirectory=/var/www/Wikijs
    
    [Install]
    WantedBy=multi-user.target
  20. Przelogowuję demona systemctl.
    sudo systemctl daemon-reload
  21. Włączam usługę Wiki.js.
    sudo systemctl enable wikijs
  22. Uruchamiam usługę Wiki.js.
    sudo systemctl start wikijs
  23. Sprawdzam status usługi Wiki.js.
    sudo systemctl status wikijs
  24. Tworzę konfigurację strony dla Apache`a.
    sudo nano /etc/apache2/sites-available/wikijs.conf
    <VirtualHost *:80>
        ServerName wiki.grzegorzwita.it
        ServerAdmin admin@grzegorzwita.it
        Redirect / https://wiki.grzegorzwita.it
    </VirtualHost>
    
    <VirtualHost *:443>
        ServerName wiki.grzegorzwita.it
        ServerAdmin admin@grzegorzwita.it
    
        DocumentRoot /var/www/Wikijs/
        ProxyPass / http://127.0.0.1:3000/
        ProxyPassReverse / http://127.0.0.1:3000/
    
        ErrorLog ${APACHE_LOG_DIR}/error_wikijs.log
        CustomLog ${APACHE_LOG_DIR}/access_wikijs.log combined
    
        SSLEngine on
        SSLCertificateFile /etc/letsencrypt/live/grzegorzwita.it/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/grzegorzwita.it/privkey.pem
    </VirtualHost>
  25. Włączam konfigurację strony.
    sudo a2ensite wikijs.conf
  26. Restartuję usługę Apache`a.
    sudo systemctl restart apache2

Przechodzę do przeglądarki na skonfigurowany adres i dokańczam konfigurację.

//Invoice Ninja

  1. Przygotowuję katalog na potrzeby Invoice Ninja.
    sudo mkdir /var/www/InvoiceNinja
  2. Pobieram archiwum systemu z repozytorium (w moim przypadku była to wersja 5.10.8, w chwili kiedy to czytasz na pewno dostępna jest już nowsza wersja).
    sudo wget https://github.com/invoiceninja/invoiceninja/releases/download/v5.10.8/invoiceninja.tar
  3. Rozpakowuję archiwum programu do katalogu docelowego.
    sudo tar xzf invoiceninja.tar -C /var/www/InvoiceNinja/
  4. Usuwam pobrane archiwum.
    sudo rm invoiceninja.tar
  5. Loguję się do serwera MySQL.
    sudo mysql -u root -p
  6. Tworzę bazę danych dla Invoice Ninja.
    CREATE DATABASE invoiceninja;
  7. Tworzę użytkownika do bazy danych dla Invoice Ninja.
    CREATE USER 'invoiceninja_dba'@'localhost' IDENTIFIED WITH caching_sha2_password BY '8arDzo_Sk0mp1ikow4N3_Ha$LO!';
  8. Nadaję odpowiednie uprawnienia utworzonemu użytkownikowi.
    GRANT ALL ON invoiceninja.* TO 'invoiceninja_dba'@'localhost';
  9. Wprowadzam zmiany w życie.
    FLUSH PRIVILEGES;
  10. Wychodzę z serwera bazy danych.
    EXIT
  11. Przygotowuję plik konfiguracyjny.
    sudo cp /var/www/InvoiceNinja/.env.example /var/www/InvoiceNinja/.env
  12. Ustawiam plik konfiguracyjny.
    sudo nano /var/www/InvoiceNinja/.env
    [...]
    DB_HOST=localhost
    DB_DATABASE=invoiceninja
    DB_USERNAME=invoiceninja_dba
    DB_PASSWORD=8arDzo_Sk0mp1ikow4N3_Ha$LO!
    DB_PORT=3306
    [...]
    PDF_GENERATOR=snappdf
    [...]
    PHANTOMJS_SECRET="8arDzo_Sk0mp1ikow4N3_Ha$LO!"
    
    UPDATE_SECRET="8arDzo_Sk0mp1ikow4N3_Ha$LO!"
    WEBCRON_SECRET="8arDzo_Sk0mp1ikow4N3_Ha$LO!"
    [...]
    EXPANDED_LOGGING=true
  13. Ustawiam rekurencyjnie właściciela i grupę dla wszystkich katalogów i plików na www-data.
    sudo chown -R www-data:www-data /var/www/InvoiceNinja/
  14. Ustawiam uprawnienia dla katalogów na 755, a plików na 644.
    sudo find /var/www/InvoiceNinja/ -type d -exec chmod 755 {} \;
    sudo find /var/www/InvoiceNinja/ -type f -exec chmod 644 {} \;
  15. Ustawiam uprawnienia na 740 dla pliku konfiguracyjnego.
    sudo chmod 740 /var/www/InvoiceNinja/.env
  16. Ustawiam właściciela i grupę na root dla katalogu nadrzędnego.
    sudo chown root:root /var/www/InvoiceNinja/
  17. Tworzę konfigurację strony dla Apache`a.
    sudo nano /etc/apache2/sites-available/invoiceninja.conf
  18. Aktualizuję i ustawiam odpowiednie uprawnienia dla snappdf w celu naprawy generowania podglądu plików PDF w systemie. Do wersji 5.10.13 każda instalacja lub aktualizacja systemu (np. z wersji 5.10.8 do 5.10.10) wymagała ponownego wykonania poniższych poleceń. Na nowszych wersjach (np. aktualizacja z 5.10.10 do 5.10.26) nie trzeba już tego robić.
    sudo chmod 744 /var/www/InvoiceNinja/vendor/bin/snappdf && sudo -u www-data /var/www/InvoiceNinja/vendor/bin/snappdf --force download && sudo chmod 644 /var/www/InvoiceNinja/vendor/bin/snappdf
  19. Instaluję dodatkowe pakiety wymagane przez snappdf.
    sudo apt-get install fonts-liberation libasound2 libatk1.0-0 libatk-bridge2.0-0 libgbm1 libpango1.0-0 libxcomposite1 libxdamage1 libxfixes3 libxkbcommon0 libxrandr2 -y
  20. Aktualizuję plik hosts.
    sudo sed -i "s/127.0.0.1 localhost/127.0.0.1 localhost system.grzegorzwita.it/" /etc/hosts
  21. Dodanę cron`y dla użytkownika www-data.
    sudo -u www-data crontab -e
    [...]
    #InvoiceNinja
    #0 8 * * * php /var/www/InvoiceNinja/artisan ninja:send-recurring >> /dev/null
    #0 8 * * * php /var/www/InvoiceNinja/artisan ninja:send-reminders >> /dev/null
    * * * * * php /var/www/InvoiceNinja/artisan schedule:run >> /dev/null 2>&1
    * * * * * php /var/www/InvoiceNinja/artisan optimize >> /dev/null 2>&1
  22. Przechodzę do katalogu Invoice Ninja.
    cd /var/www/InvoiceNinja/
  23. Generuję klucz.
    sudo -u www-data php artisan key:generate
  24. Uzbrajam bazę danych.
    sudo -u www-data php artisan migrate
  25. Optymalizuję konfigurację.
    sudo -u www-data php artisan optimize
  26. Tworzę konfigurację strony dla Apache`a.
    sudo nano /etc/apache2/sites-available/invoiceninja.conf
    <VirtualHost *:80>
        ServerName system.grzegorzwita.it
        ServerAdmin admin@grzegorzwita.it
        Redirect / https://system.grzegorzwita.it
    </VirtualHost>
    
    <VirtualHost *:443>
        ServerName system.grzegorzwita.it
        ServerAdmin admin@grzegorzwita.it
    
        DocumentRoot /var/www/InvoiceNinja/public/
    
        <Directory /var/www/InvoiceNinja/public/>
            DirectoryIndex index.php
            Options +FollowSymLinks
            AllowOverride All
            Require all granted
        </Directory>
    
        ErrorLog ${APACHE_LOG_DIR}/error_invoiceninja.log
        CustomLog ${APACHE_LOG_DIR}/access_invoiceninja.log combined
    
        SSLEngine on
        SSLCertificateFile /etc/letsencrypt/live/grzegorzwita.it/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/grzegorzwita.it/privkey.pem
    </VirtualHost>
  27. Włączam konfigurację strony.
    sudo a2ensite invoiceninja.conf
  28. Restartuję usługę Apache`a.
    sudo systemctl restart apache2

//GoAccess

  1. Instaluję pakiet.
    sudo nano /root/goaccess.sh
  2. Przygotowuję konfigurację.
    sudo apt-get install goaccess -y
    #!/bin/bash
    goaccess /var/log/apache2/access.log -o /var/www/grzegorzwitait/statystyka.html --log-format=COMBINED --real-time-html --persist --restore --db-path /var/www/grzegorzwitait/tmp/ --real-os --all-static-files --ssl-cert=/etc/letsencrypt/live/grzegorzwita.it/fullchain.pem --ssl-key=/etc/letsencrypt/live/grzegorzwita.it/privkey.pem
  3. Ustawiam uprawnienia pliku na 740, abym mógł go uruchamiać.
    sudo chmod 740 /root/goaccess.sh
  4. Ustawiam cron`a.
    sudo crontab -e
    [...]
    @reboot /root/goaccess.sh >> dev
    
  5. Udostępniam na zaporze sieciowej port 7890.
    sudo ufw allow from any to any port 7890 proto tcp

//Kopia zapasowa

Zaktualizowałem swój pierwotny skrypt kopia_zapasowa.sh, aby wykonywał kopię głównej strony internetowej wraz z wszystkimi subdomenami oraz ich bazami danych.

Dodatkowo zmieniłem wcześniej wykorzystywany, a już nierozwijany pakiet p7zip-full (zawierający 7-Zip 16.04) na 7-Zip 24.07, który pobrałem bezpośrednio z oficjalnej strony projektu. Stary 7-Zip, dostępny w repozytoriach Ubuntu, działa cały czas, jednak doskwiera już mu wiek, co widać na nowszych procesorach, a taki mam teraz na VPS`ie. Napiszę tylko, że czas wykonania kopii zapasowej ponad 137 000 plików rozproszonych w ponad 17 000 folderów o łącznej wadze przekraczającej 2,6 GB (spakowany plik *.7z ma ok. 702 MB)  zmniejszył się o 10 minut - z 27 do 17 minut w porównaniu ze starym pakietem.

  1. Tworzę katalog do przechowywania plików kopii zapasowej i logów w swoim katalogu domowym.
    mkdir /home/grzegorz_wita/backup
  2. Przygotowuję skrypt w wybranym katalogu.
    sudo nano /root/kopia_zapasowa.sh
    #!/bin/bash
    DATE=$(date +"%Y-%m-%d")
    
    tar -caf - /var/www/grzegorzwitait -P | 7zz a -si /var/www/grzegorzwitait.tar.7z
    tar -caf - /var/www/BookStack -P | 7zz a -si /var/www/BookStack.tar.7z
    tar -caf - /var/www/Wikijs -P | 7zz a -si /var/www/Wikijs.tar.7z
    tar -caf - /var/www/InvoiceNinja -P | 7zz a -si /var/www/InvoiceNinja.tar.7z
    7zz e /var/www/grzegorzwitait.tar.7z -o/var/www/
    7zz e /var/www/BookStack.tar.7z -o/var/www/
    7zz e /var/www/Wikijs.tar.7z -o/var/www/
    7zz e /var/www/InvoiceNinja.tar.7z -o/var/www/
    rm -f -R /var/www/*.tar.7z
    mv /var/www/grzegorzwitait.tar /var/www/grzegorzwitait_$DATE.tar
    mv /var/www/BookStack.tar /var/www/BookStack_$DATE.tar
    mv /var/www/Wikijs.tar /var/www/Wikijs_$DATE.tar
    mv /var/www/InvoiceNinja.tar /var/www/InvoiceNinja_$DATE.tar
    mysqldump --host=localhost --user=root --password='8arDzo_Sk0mp1ikow4N3_Ha$LO!' grzegorzwitait_dba > /var/www/mysql_grzegorzwitait_$DATE.sql
    mysqldump --host=localhost --user=root --password='8arDzo_Sk0mp1ikow4N3_Ha$LO!' bookstack > /var/www/mysql_bookstack_$DATE.sql
    mysqldump --host=localhost --user=root --password='8arDzo_Sk0mp1ikow4N3_Ha$LO!' wikijs > /var/www/mysql_wikijs_$DATE.sql
    mysqldump --host=localhost --user=root --password='8arDzo_Sk0mp1ikow4N3_Ha$LO!' invoiceninja > /var/www/mysql_invoiceninja_$DATE.sql
    7zz a -t7z -mhe=on -pmN1gdy_nie-zgadni3szhaha -m0=lzma -mx=9 -mfb=64 -md=32m -ms=on /var/www/grzegorz_wita_$DATE.7z /var/www/*.tar /var/www/*.sql
    mv /var/www/grzegorz_wita_$DATE.7z /home/grzegorz_wita/backup/
    find /home/grzegorz_wita/backup/ -type f -mtime +7 -delete
    find /var/www/ -maxdepth 1 -type f -delete
  3. Ustawiam cron job`a, aby uruchamiał skrypt codziennie o 20:00.
    sudo crontab -e
    0 20 * * * /root/kopia_zapasowa.sh >> /home/grzegorz_wita/backup/kopia_zapasowa_`date +\%Y-\%m-\%d`.log 2>&1
  4. Ustawiam uprawnienia pliku na 740, aby plik był wykonywalny.
    sudo chmod 740 /root/kopia_zapasowa.sh
0 komentarzy

Szybki kontakt

Masz pytania? Napisz