Select Page

by | 09. 06. 2020

Jak jsem v cloudu spustil svoji vlastní aplikaci Chatgo

V tomto textu si odložím postup, jak jsem spustil svoji vlastní aplikaci Chatgo.cz v cloudu Digital Ocean. Chatgo je MVP platforma pro tvorbu a správu Messenger zákaznického chatu pro web a eshop. 

Chatgo jsem vytvořil s cílem umožnit brandům komunikovat se zákazníky na webu tak, jak lidé komunikují se svou rodinou a přáteli. Jednoduše, přes mobil, přes Messenger.

Co je to MVP?

 

  • MVP je minimální životaschopný projekt.
  • Přináší zákazníkovi vysokou přidanou hodnotu
  • Obsahuje minimum funkcí, ale jsou to ty nejpodstatnější.
  • Přináší skvělý uživatelský zážit
  • Slouží k otestování zájmu o budoucí plnohodnotný produkt.

Jak publikovat vlastní side projekt s minimálními náklady

 

Side projekty jsou skvělé pro vyzkoušení nových technologií a zároveň podnikatelských nápadů. Vytvoření aplikace je jen malá část celkové práce. Aplikaci musíme někde publikovat, spravovat a propagovat. Dnes si sem odložím svůj postup, jak jsem spustil vlastní aplikaci v cloudu Digital Ocean.

 

Digital Ocean

 

Digital Ocean jsem si zvolil z důvodu velmi příznivé cennové politiky, skvělé dokumentaci a celkovému přístupu developer first.

Chatgo je klasická webová Spring Boot aplikace, která využívá relační databázi MySQL. Celé MVP provozuji na dvou tzv. dropletech (VPS) v celkové cenně $12 za měsíc.

 

Databáze MySQL

 

Po vytvoření účtu a přihlášení do dashboardu Digital Ocean nejprve založíme projekt. Pod tímto projektem budeme dále vytvářet virtuální servery (droplety).

Digital Ocean nabízí na svém Market Place one-click MySQL droplet, který obsahuje MySQL databázi a phpMyAdmin konzoli.

Klikneme na vytvořit MySQL Droplet.

Pro databázi prozatím postačí základní droplet 1CPU, 1GB RAM, 25 GB Disk a OS Ubuntu linux. Cena Dropletu je $5 za měsíc. 

Dále zvolíme lokalitu datového centra. Nahrajeme veřejnou část svého SSH klíče pro autentizaci a zapneme zálohování za cenu $1 za měsíc. 

 

Nastavení firewall

 

Po naistalování MySQL dropletu se automaticky nastaví a zapne firewall dle následujícího obrázku. Přes HTTP a HTTPS je dostupná konzole phpMyAdmin a lze tedy tyto porty následně zablokovat.

Port 3306 povolíme pouze pro ip adresu dropletů, kde je bude naistalována aplikace. V obrázku mám tento droplet otagován jako “app”.

Konzole phpMyAdmin

 

Webová konzole je dostupná na adrese následující adrese, kde <mysql_doplet_ip_address> naradíme IP adresou dropletu.

https://<mysql_doplet_ip_address>/phpmyadmin

Heslo k admin účtu phpMyAdmin je dostupné v souboru /root/.digitalocean_password.

 

MySQL uživatel pro aplikaci

 Po instalaci dropletu se automaticky založí root účet a vygenerované heslo je uvedeno v souboru /root/.digitalocean_password.

Vytvořím účet, přes který se bude připojovat Chatgo aplikace k databázi. 

  1. Připojím se přes SSH k dropletu.
  2. Připojím se k DB serveru jako root

        mysql -u root -p

  3. Vytvořím nového uživatele pomocí příkazu, kde se nahradí uživatelské jméno, IP adresa dropletu a heslo.

    mysql> CREATE USER ‘<app_user>’@'<droplet_ip_address>’ IDENTIFIED BY ‘<strong_password>’;

  4. Po vytvoření schematu databáze ještě přiřadím privilegia novému uživateli.

    mysql> GRANT SELECT, INSERT, UPDATE, DELETE ON <jmeno_db_schema>.* TO ‘<app_user>’@'<droplet_ip_address>’;

    mysql> FLUSH PRIVILEGES;

Nového uživatel <app_user> využije aplikace v connection stringu pro připojení k databázi. 

 

VPS pro aplikaci

 

Droplet Ubuntu Linux

 

Pro aplikaci a reverzní proxy server prozatím také postačí základní droplet 1CPU, 1GB RAM, 25 GB Disk a OS Ubuntu linux. Cena Dropletu je $5 za měsíc. Droplet pojmenuji jako App droplet a přidám mu tag “app”. Pomocí tohoto tagu se lze odkazovat na droplet například v nastavení firewallu pro další droplety.

 

Dále zvolíme lokalitu datového centra. Nahrajeme veřejnou část svého SSH klíče pro autentizaci a zapneme zálohování za cenu $1 za měsíc. 

Připojení k serveru přes SSH bude možné až po několika minutách. Chvíli trvá než se droplet nainstaluje.

 

Nastavení firewallu

 

Po naistalování App dropletu je ještě potřeba nastavit a zapnout firewall, kde povolíme pouze porty HTTP 80, HTTPS 443 a SSH 22. Firewall lze vytvořit v levém menu v záložce Networking/Frewalls/Create new firewall. Firewall pojmenuji jako App_Firewall a přiřadím mu App Droplet v záložce droplets.

 

Vytvoření uživatele

 

Pracovat přes root uživatele není bezpečný způsob. Budu se tedy hlásit přes SSH a spravovat droplet nově vytvořeným uživatelem s právy SUDO.

 

  1. V konzoli se přes SSH přihlásim jako root
  2. Vytvořím nového uživatele následujícím příkazem, kde nahradím <common_user> uživatelským jménem a zvolím silné heslo.

     adduser <common_user>

  3. Vložim svůj SSH public key do souboru

    /home/<common_user>/.ssh/authorized_keys

  4. Následujícím příkazem přidám práva SUDO skupiny

    usermod -aG sudo <common_user>

  5. Nyní zbývá jen vypnout možnost přihlášení SSH pro root účet.

    vim /etc/ssh/sshd_config //PermitRootLogin=no

  6. Pro případ správy souborů přes winSCP z Windows musím ještě eskalovat práva pro sftp-server přes visudo editor.

visudo

 

root ALL=(ALL:ALL) ALL
<common_user> ALL=NOPASSWD: /usr/lib/openssh/sftp-server

 

Nasměrování domény

 

U správce domény nastavím A záznam na IP adresu App Dropletu. Tato operace může trvat až 24 hodin a je nutná pro vygenerování Let’s Encrypt certifikátů pro šifrované HTTPS připojení.

Spuštění Spring Boot aplikace jako Systemd.

 

Službu Systemd budu spouštět pod nově vytvořeným aplikačním uživatelem.

  1. Vytvořím nového uživatele následujícím příkazem, kde nahradím <app_user> uživatelským jménem a zvolím silné heslo.

     adduser <app_user>

  2. V /opt vytvořím následující strukturu složek a souborů

    /opt/chatgoapp                                               <app_user>            0555
    /opt/chatgoapp/builds                                     <common_user>     0755
    /opt/chatgoapp/builds/chatgo.jar                     <common_user>     0664
    /opt/chatgoapp/config                                     <common_user>     0755
    /opt/chatgoapp/config/application.properties     <common_user>     0664
    /opt/chatgoapp/logs                                        <app_user>            0755

  3. Instalace Javy

    sudo apt-get update
    sudo apt-get install openjdk-8-jdk

  4. Vytvoření služby Systemd chatgoapp.service

    sudo vim /etc/systemd/system/chatgoapp.service

    # /etc/systemd/system/chatgoapp.service

     

    # root 0644

     

    [Unit]
    Description=Chatgo app dashboard and webhook
    After=syslog.target

     

    [Service]
    User=chatgoapp
    WorkingDirectory=/opt/chatgoapp/builds
    ExecStart=/usr/bin/java -Dspring.config.additional-location=file:/opt/chatgoapp/config/ -Dspring.profiles.active=prod -jar /opt/chatgoapp/builds/chatgo.jar
    SuccessExitStatus=143

    [Install]
    WantedBy=multi-user.target

  5. Obdobně vytvořím “druhý node” aplikace chatgoapp2.service. Slouží pro otestování loadbalanceru v následujících krocích.
  6. Spring Boot externí konfigurace

    # application-prod.properties je dobré mít externě mimo jar soubor.
    # Nemusím dělat release kvůli změně v konfiguraci

    # application-prod.properties se umístí do adresáře:
    /opt/chatgoapp/config/application-prod.properties

    # Jar se následně spouští s parametry
    -Dspring.config.additional-location=file:/opt/chatgoapp/config/
    -Dspring.profiles.active=prod

  7. Spuštění služby a její ovládání

    sudo systemctl daemon-reload  #načte změny v *.service souborech
    sudo systemctl start chatgoapp
    sudo systemctl restart chatgoapp

    sudo systemctl status chatgoapp
    sudo systemctl stop chatgoapp

  8. Automatické spuštění aplikace po rebootu systému

    sudo systemctl enable chatgoapp

  9. Systémové logy

    /var/logs/syslog

  10. Aplikační logy (Logback)

    #cesta je nastavena v logback.xml relativně k umístění #/opt/chatgoapp/builds/chatgoapp.jar

    /opt/chatgoapp/logs

  11. Problém Entrophy. Aplikace potřebuje ke svému běhu generátor náhodných čísel. Problém vzniká pokud více aplikací přistupuje ke zdroji náhodných čísel najednou. Jelikož je přístup blokující, tak může docházet k zamrzání aplikace. Toto se projeví v logu následovně.

     2020-10-06 12:35:25.761 WARN CHATGO-APP /chatgo-app chatgo-app Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [101,779] milliseconds. ##### http-nio-8080-exec-5.o.a.j.l.DirectJDKLog.log():173

    2020-10-06 12:35:25.770 WARN CHATGO-APP /chatgo-app chatgo-app Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [97,437] milliseconds. ##### http-nio-8080-exec-3.o.a.j.l.DirectJDKLog.log():173

    2020-10-06 12:35:25.771 WARN CHATGO-APP /chatgo-app chatgo-app Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [97,593] milliseconds. ##### http-nio-8080-exec-9.o.a.j.l.DirectJDKLog.log():173

Snadným a elegantním řešením je instalace programu haveged. Poslední příkaz spustí generátor náhodných čísel i po rebootu systému.

sudo apt-get update
sudo apt-get install haveged
sudo update-rc.d haveged defaults

 

Reverzní proxy NGINX 

Jako reverzní proxy a loadbalancer jsem zvolil NGINX. Bude sloužit pro terminaci SSL a rozložení zátěže.

 

  1. Úprava aplikace 


    Vykreslení absolutních odkazů může být za proxy serverem problém. Je nutné nakonfigurovat presměrovaní hlaviček.

    # application-prod.properties
    server.use-forward-headers=true

  2. Instalace NGINX

    sudo apt-get update
    sudo apt-get install nginx

    ps aux | grep nginx

    #root  nginx: master process /usr/sbin/nginx -g daemon on; #master_process on;
    #www-data  nginx: worker process

    sudo systemctl status nginx 

    sudo systemctl stop nginx
    sudo systemctl start nginx
    sudo systemctl reload nginx  #bez výpadku

  3. Spuštění po rebootu systému

    sudo systemctl enable nginx 

  4. Logování

    access_log:   /var/log/nginx/access.log
    error_log:     /var/log/nginx/error.log;

  5. Základní konfigurace

    # Vytvořím konfiguračním soubor 
    /etc/nginx/sites-available/app.chatgo.cz root 0644

    # Kontrola kofiguračního souboru
    sudo nginx -t

    # Reload bez výpadku
    sudo systemctl reload nginx

     

    # Dále soubor nalinkuji do adresáře aktivních stránek
    sudo ln -s /etc/nginx/sites-available/app.chatgo.cz /etc/nginx/sites-enabled/app.chatgo.cz

     

    # Celý výpis konfiguračního souboru app.chatgo.cz

    upstream appservers{
       ip_hash;
       server localhost:8080 ;
       server localhost:8081 ;
    }

     

    server {
        server_name app.chatgo.cz;
        add_header X_Frame_Options “SAMEORIGIN”;

        location / {
            proxy_pass http://appservers;
        }

     

        error_page 500 502 503 504 /custom_50x.html;
        location = /custom_50x.html {
              root /usr/share/nginx/html;
              internal;
        }

     

         listen 443 ssl; # managed by Certbot
         ssl_certificate /etc/letsencrypt/live/app.chatgo.cz/fullchain.pem; #           # managed by Certbot

         ssl_certificate_key /etc/letsencrypt/live/app.chatgo.cz/privkey.pem;         #  managed by Certbot

         include /etc/letsencrypt/options-ssl-nginx.conf;
         # managed by Certbot

          ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
         # managed by Certbot

    }

    # Redirect all traffic to HTTPS
    server {
            server_name app.chatgo.cz;
            listen 80;
            return 301 https://$host$request_uri;
    }

  6. SSL Let’s Encrypt. Využívám bezplatné 90-ti denní certifikáty s automatickou obnovou. Následující příkazy zapisují také do NGINX konfigurace viz výše. Řádky spravované Certbotem jsou označeny příslušným komentářem.

    #Instalace aplikace certbot
    sudo apt-get install certbot python3-certbot-nginx

     

    # Získám SSL certifikát pro dříve přesměrovanou doménu app.chatgo.cz
    sudo certbot ––nginx -d app.chatgo.cz

     

    # Automatická obnova po 90ti dnech
    sudo certbot renew ––nginx ––dry-run

     

    # Verifikace demona pro obnovu certifikatu
    sudo systemctl status certbot.timer

  7. Loadbalancing

    # Loadbalancing je nakonfigurovám v app.chatgo.cz souboru pomocí  #upstreamu. Odkazuje na dvě Systemd služby na portech 8080 a 8081. #Položka ip_hash udává, že je zapnutý sticky session mode (jeden #uživatel je vždy směrovám promárně na stejnou instanci.). V základním #nastavení je loadbalancig typu round robin.

    upstream appservers {
       ip_hash;
       server localhost:8080 ;
       server localhost:8081 ;
    }

  8. Základní hardening

    # Skrytí verze NGINX v hlavičkách

     

    http {
         …
         server_tokens off;
         …
    }


    #same origin 

    server {
          server_name app.chatgo.cz;
          add_header X_Frame_Options “SAMEORIGIN”;
          …
    }


    # Přesměrování pouze na HTTPS

    server {
            server_name app.chatgo.cz;
            listen 80;
            return 301 https://$host$request_uri;
    }

     

     

    # Vlastní chybová stránka

     

    /usr/share/nginx/html/custom_50x.html zdusatko 0664

    error_page 500 502 503 504 /custom_50x.html;
    location = /custom_50x.html {
            root /usr/share/nginx/html;
            internal;
    }

 

Závěr

Huráá cool. Vše je nastavené a běží. Na chatgo aplikaci se můžete mrknout zde.