Linux-palvelimet – Harjoitus 5

Osallistun Haaga-Helia ammattikorkeakoulussa Linux-palvelimet kurssille, jonka opettajana toimii Tero Karvinen. Kaikki tehtävät ovat hänen verkkosivuiltaan http://terokarvinen.com/.

Suoritan tehtävän pöytätietokoneellani, jossa pyörii Debian 9.7. ja samalla käytän Digital Oceanilta vuokrattua virtuaalipalvelinta, jossa pyörii Ubuntu 18.04.

Tehtävänanto kuuluu seuraavasti:

a) Asenna SSH-demoni
b) Suojaa kone tulimuurilla, mutta tee ensin reikä SSH:lle
c) Siirrä tiedostoja ssh:lla
d) Automatisoi kirjatuminen julkisen avaimen menetelmällä
j) Asenna ja konfiguroi ja käynnistä sysstat-paketti. Tarkista sar-komennolla, että se on päällä, esim. näyttää lokimerkinnän “Linux reboot…”. Anna sysstatin pyöriä päivä tai pari. Tutki kuormitushistoriaa sysstatin komennoilla sar, iostat, pidstat… Analysoi tulokset, eli selitä perusteellisesti mitä tulokset tarkoittavat.
i) (Ryhmä 7 tiistai varsinainen tehtävä, muille vapaaehtoinen): Ratkaise Scan of the Month 15. Katso vinkkejä Forensic File Recovery with Linux – Undelete. Älä katso malliratkaisua netistä, ellet ole jumissa, ja merkitse raporttiisi, jos katsoit. Kuva sisältää oikeaa haittakoodia, älä käsittele sitä arvokkailla tietokoneilla tai työnantajan tuotantoverkossa, äläkä aja siltä löytyviä ohjelmia. Kaikki vastaukset löytyvät kuvasta, tässä tehtävässä ei tutkita mitään muita järjestelmiä.
e) (vapaaehtoinen) Vaihda sshd:n portti
f) (vapaaehtoinen) Salli vain ryhmän sshers jäsenten kirjautuminen. Lisää itsesi tähän ryhmään.
g) (vapaaehtoinen) Liitä hakemisto sshfs:n avulla verkon yli.

A.) SSH:n asennus

Ensimmäisessä tehtävässä sanotaan vain, että tulee asentaa SSH-demoni. Kello on 12:11. Se asennettaan tuttuun tapaan komennolla $ sudo apt install ssh. Kun se on asennettu, niin sen voi vielä tarkistaa, katsomalla hakemiston /etc komennolla $ cd /etc/. Sitten voi joko etsiä manuaalisesti itse tai antaa komennon $ ls |grep ssh, jolloin pitäisi näkyä SSH-demonin hakemisto, jos se on asennettuna. Kello on 12:17.

B.) Tulimuuri ja SSH-reikä

Toisessa tehtävässä oli tarkoitus suojata kone tulimuurilla ja asettaa reikä SSH:lla. Kello on 12:30. Minulla on tulimuuri jo laitettu pystyyn ja siellä on HTTP- ja HTTPS-reiät laitettuna. Halusin statuksen tehtävää varten, joten etsin, kuinka voin näyttää tulimuurin nykyisen statuksen. Täältä löysin, että komento on $ sudo ufw status verbose. Kun annoin komennon, niin se sylkäisi tällaista:

Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip

To Action From
-- ------ ----
22/tcp ALLOW IN Anywhere 
80/tcp ALLOW IN Anywhere 
443/tcp ALLOW IN Anywhere 
22/tcp (v6) ALLOW IN Anywhere (v6) 
80/tcp (v6) ALLOW IN Anywhere (v6) 
443/tcp (v6) ALLOW IN Anywhere (v6)

Siispä tästä voimme nähdä, että tulimuuri on aktiivinen ja vain portit 22, 80 ja 443 ovat avattuja.

Jos olisimme halunneet laittaa tulimuurin nollasta päälle, niin tämän ohjeen mukaan, se kävisi vain kahdella komennolla. $ sudo ufw allow 22/tcp ja sitten vaan $ sudo ufw enable. Näillä komennoilla tulimuurissa olisi tarvittavat vaatimukset eli päällä ja SSH-portti auki. Kello on 12:41.

C.) SSH-tiedostosiirto

Seuraavassa tehtävässä olisi tarkoitus siirtää tiedostoja SSH:lla. Toisin ilmaistuna SCP-menetelmällä tai Rsyncillä. Ei käytännössä ole niinkään väliä, kumpaa menetelmää käytän, sillä ajattelin siirtää vain yhden tiedoston demoa varten. Kello on 12:44.

Teen testitiedoston pöytäkoneelleni. $ nano foo.txt, jonka jälkeen laitan tiedostoon jotain pientä demotekstiä. Tämän jälkeen tallennan tekstitiedoston. Sitten yritän siirtää tämän tiedoston palvelimelleni vaikka tällä kertaa Rsyncillä. Sitten vaan komento $ rsync foo.txt santeri@santerisiirila.me: (Huom! Kaksoispiste komennossa on tärkeä, eikä toimi ilman!) Tämän jälkeen kävin katsomassa palvelimeltani, oliko se siirtynyt käyttäjäni kotihakemistoon.

Tadaa!

screenshot-from-2019-02-23-12-54-47.png

Halusin kokeilla vielä jotain isompaa, koska miksikäs ei?

Menin metsästämään pöytäkoneestani jotain paria kilotavua isompaa tiedostoa/hakemistoa. Tähän on hyvä käyttää $ ls -lh, mutta varmasti voisi find-komentoa myös hyödyntää. Itse etsin manuaalisesti tuolla aiemmin mainitsemalla komennolla. Löysin vanhan mobiiliohjelmointiprojektin ja siinähän on node-modules, joka tunnetusti vie tilaa ihan kiitettävästi. Siipä päätän siirtää tuon hakemiston.

$ rsync viskiprojekti santeri@santerisiirila.me: -r -v –progress

Löysin pienet ohjeet, jotta saan progressin ja kokonaisen kansion siirrettyä. Voit lukea lähteet täältä ja täältä. Näin sain rekursiivisesti siirrettyä koko hakemiston palvelimelle. Tältä näytti lopputulos:

Screenshot from 2019-02-23 13-20-02.png

Vielä käydään katsomassa palvelimelta, mitä sinne kuuluu:

Screenshot from 2019-02-23 13-22-45.png

Hyvältä näyttää! Kello on 13:23.

D.) Julkinen avain

Tässä tehtävässä halutaan automatisoida kirjautuminen palvelimelle julkisen avaimen menetelmällä. Kello on 13:25.

Olen tämän jo tehnyt, mutta se tapahtuisi siis siten, että luodaan aluksi paikalliselle koneelle SSH-keygenillä itselleen julkinen ja salainen avain. Siispä $ ssh-keygen. Tämän jälkeen ohjelma kysyy kysymyksiä, jotka voi läpäistä vain rämppäämällä enteriä, mutta kannattaa silti lukea ne läpi. Noin, sinulle on nyt generoitu avainpari. Tämän jälkeen tulee vain asettaa sinun julkinen avain palvelimelle ssh-copy-id-komennolla. Esimerkkinä:

$ ssh-copy-id -i .ssh/id_rsa.pub santeri@santerisiirila.me

Tämän jälkeen joudut vielä kirjoittamaan salasanan kerran etähallintakoneelle, mutta sitten avain on asetettu, etkä enää tule tarvitsemaan salasanaa paitsi mahdollisesti joskus sudo-komentoihin. Minä itse saan tästä varoituksen, koska olen jo asettanut avaimet palvelimelle. Tämän jälkeen kuitenkin, kaiken pitäisi olla valmista. Kello on 13:37.

J.) Sysstat

Tässä tehtävässä oli tarkoitus asentaa Sysstat-paketti ja katsoa sen toimivuus. Lopulta pitää antaa sen pyöriä vaikka noin päivän omin voimin, jonka jälkeen voi katsoa tuloksia. Kello on 13:50.

Asennetaan aluksi Sysstat komennolla $ sudo apt install sysstat. Kun Sysstat on asennettu, niin voidaan konfiguroida se oikein. Eli siis, tämän ohjeen mukaan, kun haluaa aloittaa datan keräyksen, niin vain mennään aluksi komennolla $ cd /etc/default konfiguroimaan Systatin oma tiedosto. Sitten voidaan $ sudoedit sysstat -komennolla muokata tiedostosta kohta ENABLED=”false” tähän: ENABLED=”true”. Tämän jälkeen vain käynnistetään Sysstat-demoni uudestaan komennolla $ sudo service sysstat restart. Sitten demonin pitäisi kertätä tietoa, mutta sen voi vielä tarkistaa vaikka komennolla $ sar -r.

Screenshot from 2019-02-23 14-02-41.png

Tadaa, se toimii! Huomenna tullaan tutkimaan tuota lisää, mutta nyt ei ole vielä tarpeeksi tietoa. Kello on 14:03.

I.) Scan of the Month 15

Seuraavaksi olisi tarkoitus suorittaa Scan of the Month 15 -haaste. Haaste on löydettävissä tältä sivulta: http://old.honeynet.org/scans/scan15/ Kello on 14:31.

Latasin aluksi linkistä, tar.gz-tiedoston, jonka sitten purin komennolla $ tar -xzf honeynet.tar.gz. Nyt samassa kansiossa on /honeynet-kansio. Siellä oli vain README- ja honeypot.hda8.dd (mount image) -tiedostot.

En tiennyt ollenkaan, miten tätä tehtävää tulisi lähteä selvittämään, joten otin yhden mallivastauksista ja tein hänen kirjoitelmansa mukaan kaikki vaiheet. Tässä linkki tämän henkilön kirjoitelmaan: http://old.honeynet.org/scans/scan15/proj/som32.txt. Hänen mukaansa tämä image-tiedosto tulisi mountata read only -moodissa turvallisuussyistä, joten tein juuri niin. $ sudo mount honeypot.hda8.dd /mnt/test -oloop,ro oli komento, jota käytin tähän.

Kun olin mountannut kyseisen imagen, putosin kärryiltä aivan täysin. Jopa vaikka luinkin mallivastauksia. En ymmärrä, miten asiat tässä tapahtuvat ja vaikka on komentoja kerrottu teksteissä, niin siltikään en ymmärrä mitä mikäkin komento tekee. En koe tästä olevan hyötyä, koska vaikka tekisin kaiken mitä ohjeessa sanotaan, niin en silti ymmärtäisi mitä tapahtuu. Jätän tämän tehtävän tähän. Kello on 15:23.

Tässä on tekstejä, mitä yritin hyödyntää:

http://old.honeynet.org/scans/scan15/som/som33.html
http://old.honeynet.org/scans/scan15/som/som6.txt
http://old.honeynet.org/scans/scan15/som/som19.txt

G.) SSHFS

Katkerana, kun en saanut edettyä tuossa edellisessä tehtävässä, niin päätin tehdä jotain, jonka olen jo tehnyt joskus. Tässä tehtävässä olisi tarkoitus siis käyttää SSHFS:ää ja siten mountata itselleen uusi asema, joka olisi vaikkapa palvelimella. Tarkoitukseni on siis mountata oman palvelimeni kotihakemisto pöytäkoneelleni. Kello on 15:40.

Ensiksi asennetaan SSHFS, $ sudo apt install sshfs. Sitten loin kotihakemistooni mnt-hakemiston, jota aion käyttää mount pointina /mnt-hakemiston sijaan. $ mkdir mnt $ cd mnt. Sitten olisikin tarkoitus mountata tämä palvelimeni tuohon hakemistoon. Käytän apunani opettajamme ohjetta.

$ cd
$ sshfs santeri@santerisiirila.me: mnt/
$ cd mnt/
$ ls
foo.txt  public_html  publicsites  viskiprojekti

Kuten tuosta voi päätellä, niin mount toimi oletetetusti. Testaan vielä lisätä vaikka jonkin tiedoston ja katsoa, että tuleeko se palvelimelle myös:

$ nano testi.txt
$ ls 
foo.txt  public_html  publicsites  testi.txt  viskiprojekti

Siirryin palvelimelleni:

santeri@ubuntu-s-1vcpu-2gb-fra1-01:~$ ls
foo.txt  public_html  publicsites  testi.txt  viskiprojekti

Se toimii, kuten toivottukin.

Nyt haluan vielä tehdä sen oikeasti oikeaoppisesti, eikä siten, että kaikki menee nyt sekaisin, jos yhteys menisikin poikki. Siispä unmountaan ensiksi komennolla $ fusermount -u /home/santeri/mnt. Sitten vaan oikeaoppinen mount vielä: $ mount sshfs -o reconnect,ServerAliveInterval=5,ServerAliveCountMax=3 santeri@santerisiirila.me: mnt/

Tämän jälkeen testasin vielä samalla tavalla kuin aiemmassakin esimerkissä ja kaikki edelleen toimi. Kello on 16:00.

Jatkoa Sysstatiin

Kello on 18:43 seuraavaa päivää, eli siitä on yli vuorokausi, kun asensimme Sysstat-paketin koneellemme ja laitoimme datan keräyksen aktiiviseksi. Nyt jos käytämme vaikkapa komentoa $ sar, niin saamme jo paljon mielenkiintoisempia tuloksia kuin viimeksi. Minulla tuo komento antoi tällaista:

Screenshot from 2019-02-24 18-46-08.png

Tässähän näkyy, että CPU:n käyttöaste on todella pieni järjestelmässäni. %Idle on koko ajan yli 99 %, eli toisin sanottuna järjestelmäni kaipaisi lisätekemistä yli 99 % ajasta. Ainakin tämän lähteen mukaan. No, ihan hyvä tietää, ettei tietokoneen CPU ainakaan ole ylikuormitettu.

$ iostat -komennolla saatiin taas tällaista outputia:

Screenshot from 2019-02-24 18-55-53.png

Tämän ohjeen mukaan, %user on käyttöaste käyttäjätasolla (ohjelmat), %nice on käyttäjätasolla oleva käyttöaste “nice”-prioriteetilla, %system on taas kernel-tasolla tapahtuva suoritinkäyttö, %iowait kertoo idle-ajasta kun järjestelmä on saanut suuren I/O-pyynnön levylle, %steal viittaa aikaan kun hypervisor on palvellut jotain toista virtuaaliprosessoria ja siten odotuttanut suoritinta ja viimeiseksi %idle on vain toimettomuuden käyttöaste – suorittimella ei ole ollut tekemistä tarpeeksi.

Tuo toinen osio kertoo laitteisiin kohdistuneet kirjoitukset ja lukemiset (I/O). TPS viittaa siirtoihin sekunnissa (transfers per second), kB_read/s on luettu data (kilotavua sekunnissa), kB_wrtn/s on laitteelle kirjoitetun datan määrä (kilotavua sekunnissa), kB_read on kokonainen määrä tavuja luettu ja kB_wrtn on kokonaismäärä tavuja kirjoitettu laitteelle. Näistä voi päätellä, että palvelimelleni on kirjoitettu noin 33 miljoonaa kilotavua kokonaisuudessaan ja sieltä on luettu noin 2 miljoonaa kilotavua.

Viimeiseksi vielä, komennolla $ pidstat, joka siis myös kuuluu tähän Sysstat-pakettiin, saadaan tällainen lista:

Screenshot from 2019-02-24 19-09-41.png

Tämä näyttää vahvasti samalta kuin aiemmat statistiikkaohjelmat, mutta tässä on lisätty itse demoni, joka sitä käyttää. Listalla näkyy esimerkiksi Apache, SSH ja MySQL (MariaDB). Kuten tästäkin voisi päätellä, suoritinkäyttö ei todellakaan ole katossa, mutta tuosta voi tarvittaessa katsoa, jos jokin tuntuu syövän tehoja. Tuosta saa myös kätevästi kunkin demonin PID-numeron (Process ID). Muuta ihmeellistä en löytänyt tästä. Kello on 19:14.

 

Linux-palvelimet – Harjoitus 3

Osallistun Haaga-Helia ammattikorkeakoulussa Linux-palvelimet kurssille, jonka opettajana toimii Tero Karvinen. Kaikki tehtävät ovat hänen verkkosivuiltaan http://terokarvinen.com/.

Suoritan tehtävän pöytätietokoneellani, jossa pyörii Debian 9.7.

Tehtävänanto kuuluu seuraavasti:

Tee viisi vapaavalintaista kohtaa. Säädä vaikeustaso oikeaksi: jos olet ihan alussa ja tämä on haastavaa, tee helpoimmat a b c d i. Jos osaat jo perusteet, tee useampia tai vaikeampia kohtia. Tarkoitus on, että tehtävät tehtyäsi osaat enemmän kuin osasit ennen.
a) Asenna Apache, laita käyttäjien kotisivut (http://example.com/~tero) toimimaan. Testaa esimerkkikotisivulla.
b) Surffaa oman palvelimesi weppisivuja. Etsi Apachen lokista esimerkki onnistuneesta (200 ok) sivulatauksesta ja epäonnistuneesta (esim 404 not found) sivulatauksesta. Analysoi rivit.
c) Tee virhe weppipalvelimella ajettavaan koodiin (esim PHP tai Python), etsi se lokista ja analysoi tuo lokirivi
d) Tee virhe johonkin Apachen asetustiedostoon, etsi ja analysoi tuo rivi. Etsimiseen sopivat esimerkiksi Apachen omat lokit, syslog sekä ‘apache2ctl configtest’.
e) Asenna ja kokeile PhpMyAdmin:a tai jotain muuta valmista weppiliittymää tietokantojen hallinnointiin.
f) Tee palvelimella ajettava weppiohjelma, joka tekee käyttäjälle jonkin yksinkertaisen laskun (esim. painoindeksi BMI)
g) Tee palvelimella ajettava weppiohjelma, joka käyttää tietokantaa. Voit tehdä jonkin yksinkertaisen CRUD-ohjelman, esimerkiksi TODO-listan
h) Tee Apachelle uusi sivu, joka näkyy suoraan palvelimen pääsivulla, mutta jonka sivuja voi muokata normaalin käyttäjän oikeuksilla (name based virtual host, DocumentRoot käyttäjän kotihakemistoon).
i) Kuinka monta eri HTTP Status:ta (200, 404, 500…) saat aiheutettua lokeihin? Selitä, miten aiheutit tilanteet ja analysoi yksi rivi kustakin statuksesta.
j) Asenna LAMP (Linux, Apache, MySQL, PHP). Testaa kunkin komponentin toiminta. Testaa lopuksi kokonaisuus. (Voit aloittaa tilanteesta, jossa Linux-käyttöjärjestelmä on jo asennettu, mutta ei muita (AMP) osia.
k) Kokeile jotain Flaskin uutta ominaisuutta flask-testipalvelimessa. Voit kokeilla esim. muotteja (templates), tietokantaa tai syötteiden ottamista lomakkeilta (forms).
l) Asenna Python Flask + PostgreSQL + Apache mod WSGI. Testaa kunkin komponentin toiminta. Testaa lopuksi kokonaisuus. (vaikea)

 

Vaikka tehtävänannossa on tarkoitus tehdä vain viisi tehtävää, niin haluan silti yrittää tehdä kaikki. Tämä on kumminkin vain tavoite. Todennäköistä, että vain viisi tulee tehdyksi.

L.) Python Flask, PostgreSQL ja Apache mod WSGI

Tehtävän L oli tarkoitus ilmeisesti olla vaikein. Kyseisessä tehtävässä tulisi siis asentaa Python Flash, Postgre ja Apache mod WSGI sekä testata niiden kokonaisuus. Aloitin tehtävän noin klo 12:00

Etsiskelin hetken ja löysin ensimmäisen sivuston, joka varmaankin voisi auttaa tässä tehtävässä: https://www.digitalocean.com/community/tutorials/how-to-deploy-a-flask-application-on-an-ubuntu-vps. Sivulla olevan ohjeen mukaan, ensiksi tulisi asentaa apache2. Joten asensin sen komennolla $ sudo apt install apache2. Sen jälkeen piti ohjeen mukaan asentaa libapache2-mod-wsgi ja python-dev, joten terminaaliin tämä:
$ sudo apt install libapache2-mod-wsgi python-dev

Kaikki näytti toimivan aluksi hyvin, ei virheitä asennuksessa. Python-dev minulla olikin jo entuudestaan, joten sain vain tiedon, että se on viimeisimmässä versiossaan. Versio oli 2.7, joka vähän herätti epäilystä, sillä Python on versiossa 3.7 tällä hetkellä ja ohje oli vuodelta 2013, mutta katsotaan, miten tässä käy. Seuraavaksi tulisi enabloida mod_wsgi, joka tapahtuu ohjeen mukaan komennolla $ sudo a2enmod wsgi – tuli vain teksti “Module wsgi already enabled”.

Sitten olisikin kai tarkoitus tehdä Flask-applikaatio. Tulen tekemään sen ohjeiden mukaan, vaikka ovatkin hieman vanhat. Ohjeen mukaan pitää ensiksi mennä hakemistoon /var/www/, joten $ cd /var/www. Sen jälkeen vielä $ pwd, jotta saamme varmuuden olevamme oikeassa alihakemistossa: /var/www. Tämän jälkeen tehdään kaksi FlaskApp-hakemistoa, yksi /var/www-hakemistoon ja toinen FlaskApp-hakemiston sisälle. Sen jälkeen vielä siihen toiseen FlaskApp-hakemistoon luodaan kaksi hakemistoa static ja templates. Eli siis näin:

$ sudo mkdir FlaskApp 
$ cd FlaskApp/
$ sudo mkdir FlaskApp
$ cd FlaskApp/ 
$ sudo mkdir static templates
$ pwd
/var/www/FlaskApp/FlaskApp
$ ls
static template

Sitten luomme hakemistoon vielä __init__.py-tiedoston, joka siis tehdään vaikka näin: $ sudo nano __init__.py
Tämän jälkeen siihen tulisi laittaa tämä pätkä koodia ja sen jälkeen tallentaa:

from flask import Flask
app = Flask(__name__) 
@app.route("/") 
def hello():
    return "Hello, I love Digital Ocean!" 
if __name__ == "__main__": 
    app.run()

Näiden jälkeen asennamme pip-ohjelman, mutta minulla taitaa olla jo se. Testataan silti vielä: $ sudo apt install python-pip. Kyllä minulla se oli, mutta kannatti tarkistaa. Seuraavaksi piti asentaa virtualenv pip:llä, mutta kun annoin komennon $ sudo pip install virtualenv, niin mainittiin jälleen Python 2.7. Katsotaan miten käy lopputuloksen. Sitten luotiin virtuaaliympäristö komennolla $ sudo virtualenv venv, jossa “venv” on halutun ympäristön nimi. Sitten aktivoidaan ympäristö antamlla komento: $ source venv/bin/activate, jolloin terminaali näytti tältä: Screenshot from 2019-02-02 13-53-29
Sitten kun virtuaaliympäristö on käynnissä, niin annetaan Flaskin asennuskomento           $ sudo pip install Flask. Kaikki vaikutti asentuvan ongelmitta. Sitten testattiin toimintaa $ sudo python __init__.py, jonka jälkeen terminaali näytti tältä: Screenshot from 2019-02-02 13-57-45

Käydään katsomassa selaimella tuo http://127.0.0.1:5000.Screenshot from 2019-02-02 13-59-15.png

Sehän toimi! Sitten voidaan tappaa tuo CTRL + C -yhdistelmällä ja sitten voidaan deaktivoida tuo ympäristö komennolla deactivate. Nyt ollaan testattu, että kokonaisuus toimii edes jotenkin. Seuraavaksi pitäisi tehdä konfiguraatiotiedosto, mutta minusta tuntuu, että se on tarkoitettu vain sellaisille palvelimille, jotka on tarkoitettu tuotantoon, eikä ainoastaan pyöri localhostissa. Joten ohitamme ohjeesta kohdan neljä ja hyppäämme suoraan viidenteen.

Vielä olisi tarkoitus tehdä .wsgi-tiedosto /FlaskApp-kansioon, joten siis annetaan jälleen komentoa terminaaliin: $ cd /var/www/FlaskApp. Sitten vaikka nanolla uusi tiedosto, jonka nimi on flaskapp.wsgi. $ sudo nano flaskapp.wsgi. Laitoin tiedostoon juuri kuten ohjeessa sanotaan eli:

#!/usr/bin/python
import sys
import logging
logging.basicConfig(stream=sys.stderr)
sys.path.insert(0,"/var/www/FlaskApp/")

from FlaskApp import app as application
application.secret_key = 'Add your secret key

Sitten käynnistetään apache2 uudelleen komennolla $ sudo service apache2 restart. Katsotaan sitten vielä, miltä sivu näyttää. Näyttää edelleen samalta ja toimii. Apache2 mod WSGI ja Python Flask siis toimivat. Vielä jos saisi yhdistettyä PostgreSQL:n tähän kokonaisuuteen. Yritetään!

Ensiksi varmaankin pitäisi asentaa PostgreSQL, mutta minulla on se jo asennettu, sillä käytimme sitä Ohjelmistoprojekti 1 -kurssilla. Se asennettaisiin normaalisti $ sudo apt install postgresql -komennolla. Joten tehdään varmaan ensiksi tietokanta. Mennään siis Postgren kehotteeseen luomaan kanta. $ sudo -u postgres psql, niin saamme luotua kannan postgres-käyttäjällä. Annoin ‘CREATE DATABASE test’ -komennon, sen jälkeen yhdistin siihen komennolla: # \connect test, tämä postauksen ansiosta: https://stackoverflow.com/questions/3949876/how-to-switch-databases-in-psql. Sen jälkeen loin sinne pöydän: # create table animals (id serial primary key, name text); Kiitos tästä formaatista Tommi Santamaalle (https://tommioffinland.fi/) tästä luontiformaatista.Nyt enää testidataa pöytään ja sitten voi yrittää kokonaisuutta yhdessä. Tältä sivulta katsoin lisäysformaatin: https://www.postgresql.org/docs/9.5/sql-insert.html. Eli siis #insert into animals values (1, ‘Giraffe’), (2, ‘Hippo’), (3, Flamingo); Tämän jälkeen tarkistus komennolla select * from animals;

Screenshot from 2019-02-02 15-14-35

Kaikki on tältä osin kunnossa. Sitten testaamaan kokonaisuutta.

Löysin tällaisen sivun, missä neuvottiin, kuinka tietokantayhteys otetaan Flaskillä. http://blog.sahildiwan.com/posts/flask-and-postgresql-app-deployed-on-heroku/ Siinä käytetään Herokua, mutta kyllä varmaan toimii ilman Herokuakin. Käytin myös apuna tätä videoa https://www.youtube.com/watch?v=VQM4QcozoW4. Asensin SQL Alchemyn komennolla $ pip install flask_sqlalchemy. Nyt kannan yhdistäminen voidaan varmaankin aloittaa.

Muokkasin aiemmin tehtyä __init__.py-tiedostoa $ sudo nano __init__.py-komennolla. Muokkasin sitä tällaiseksi:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = 'postgresql://postgres:Ku1v4hk0123#"!@localhost:5432/test'
db = SQLAlchemy(app)
@app.route("/")
def hello():
return db.query("SELECT * FROM ANIMALS;")
if __name__ == "__main__":
app.run()

Tuo ei toiminut ja olen yrittänyt jo monia muitakin muotoja, mutta saan internal server erroria koodilla 500. Olen tehnyt tehtävää jo noin 4,5 tuntia, että ehkä nyt on aika tehdä muita tehtäviä, jos vaikka tajuaisin tuon tehtävän jossain välissä paremmin. Kello on 16:42.

K.) Flask-ominaisuuden testaus

Seuraavaksi oli tarkoitus testata jotain Flask-ominaisuutta. Äskeisen tehtävän takia olen jo asentanut Flaskin, joten seuraavaksi vain etsin “flask templates”, kuten mainittiin tehtävänannossa. Kello on 16:55.

Löysin tällaisen sivun: https://code-maven.com/using-templates-in-flask. Siinä yritetään hyödyntää juuri templateja, mutta en ymmärrä kauhean hyvin, että kuinka ne toimivat. Tein kolme erillistä tiedostoa juuri kuten tuolla sanottiin, mutta saan vain virheilmoituksia, joka kerta kun yritän ajaa ohjelmaa.

Tiedostoni näyttävät tältä:

__init.py__

from flask import Flask, request, render_template
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
@app.route("/")

def hello():
return render_template('echo.html')

@app.route("/echo", methods=['POST'])
def echo(): 
return "You said: " + request.form['text']

if __name__ == "__main__":
app.run()

echo.html

<form action="/echo" method="POST">
    <input name="text">
    <input type="submit" value="Echo">
    </form>

    {% if text %}
      You said: {{ text }}
    {% endif %}

echo_template.py

from flask import Flask, request, render_template
app = Flask(__name__)
 
@app.route("/")
def hello():
    return render_template('echo.html')
 
@app.route("/echo", methods=['POST'])
def echo(): 
    return render_template('echo.html', text=request.form['text'])
 
if __name__ == "__main__":
    app.run(debug=True)

Hetken aikaa pähkäiltyä ja etsiskeltyä apua, löysin tämän langan: https://stackoverflow.com/questions/23327293/flask-raises-templatenotfound-error-even-though-template-file-exists. Tässä kerrottiin, että .html-ekstension omaava tiedosto pitää sijoittaa templates-hakemistoon. Siispä siirsin echo.html-tiedoston komennolla mv echo.html /var/www/FlaskApp/FlaskApp/templates/echo.html.

Kun ajoin __init__.py-tiedoston uudelleen niin kappas, sehän aukesi:

Screenshot from 2019-02-02 17-37-53

Vielä pieni testi:

Näytti toimivan ihan hyvin. Tiedostorakenne näytti siis tältä lopuksi:

/var/www/FlaskApp/FlaskApp$ ls
echo_template.py __init__.py static templates venv

Ja templates-hakemisto vielä lisäksi:

santeri@debian:/var/www/FlaskApp/FlaskApp$ cd templates/
santeri@debian:/var/www/FlaskApp/FlaskApp/templates$ ls
echo.html

Kaikki vakutti toimivan, kuten juuri pitäisikin. Siis lopetin tehtävä tähän pisteeseen. Kello on 17:48.

J. LAMP-asennus

Seuraavaksi olisi tarkoitus asentaa LAMP, eli Linux, Apache, MariaDB/MySQL ja PHP. Linux minulla on jo, sillä teen tälläkin hetkellä Debian jakelulla näitä tehtäviä. Apache2 minulla on aiempien tehtävien ansiosta, mutta SQL-tietokanta puuttuu sekä PHP, joten asennan ne nyt. Kello on 17:55

$ sudo apt install mariadb-client mariadb-server php7.0

Sitten asetetaan toimintakuntoon. Tarkistetaan localhost, että onko siellä jo jotain odottelemassa. Screenshot from 2019-02-02 18-00-10.png

Apache vaikutti olevan toiminnassa, joten seuraavaksi katsotaan, jos saataisi PHP toimimaan localhostissa. Etsin hieman apuja hakukoneesta, sillä kaikkea en tahdo muistaa oppitunnilta. Siispä tämä sivu toimii toistaiseksi apuna: https://www.digitalocean.com/community/tutorials/how-to-install-linux-apache-mysql-php-lamp-stack-on-ubuntu-16-04 Seuraavaksi olisi kummiskin tarkoitus käydä enabloimassa PHP apache2:sta. Joten mennään Apache2-demonin hakemistoon eli /etc/apache2. Siellä vaan komento $ grep -ir php, jotta tiedetään, että mistä saadaan PHP toimintaan. Löytyi /mods-available, jossa piti vain kommentoida alimmat rivit, jotta PHP toimisi. Nyt PHP:n pitäisi tavallaan olla toiminnassa. Siispä testaamme luomalla /public_html-hakemiston kotihakemistoon.

$ cd 
$ mkdir public_html 
$ cd public_html/

Loin nopeasti index.php-tiedoston, joka on mahdollisimman yksinkertainen. Sen lähdekoodi oli tällainen:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<?php print(4 + 4)?>
</body>
</html>

Testasin käynnistää sivua, mutta tuli 404 sivulla http://localhost/~santeri. Sitten muistin, että eihän käyttäjäsivuja ole asetettu apachesta. Siispä googlailin, että miten ne enabloidaan. Menin opettajamme sivuille ja löysin sieltä tämän ohjeen: http://terokarvinen.com/2008/install-apache-web-server-on-ubuntu-4. Siinä mainittiin, että pitää laittaa tämä:

$ sudo a2enmod userdir

Sen jälkeen terminaali ilmoitti, että pitää laittaa $ systemctl restart apache2. Tein sen ja Debian kysyi salasanani. Tämän jälkeen testasin uudelleen sivua ja se toimi:

Screenshot from 2019-02-02 18-25-59

Viimeisenä pitäisi vielä laittaa MariaDB toimimaan. Joten siis ensiksi $ sudo mariadb. Sitten CREATE DATABASE TEST; Sen jälkeen USE test; (https://stackoverflow.com/questions/4005409/error-1046-no-database-selected-how-to-resolve) CREATE TABLE animals(id int primary key, name varchar(255)); (https://www.techonthenet.com/mariadb/tables/create_table.php) Sitten INSERT INTO animals VALUES (1, “Giraffe”),(2, “Tiger”),(3, “Hippo”); Tietokanta on valmis testaukseen, joten seuraavaksi enää pitää yrittää saada tieto näkymään tietokannasta.

Kello on 20:15, olen yrittänyt kymmeniltä eri sivuilta metodeja, kuinka saisin tietokantayhteyden, mutta mikään ei vain tunnu toimivan. Nämä sivut muunmuassa: https://www.tutorialspoint.com/mariadb/mariadb_create_tables.htm, http://terokarvinen.com/2018/php-database-select-and-insert-example-php-pdo, http://terokarvinen.com/2016/read-mysql-database-with-php-php-pdo ja https://www.youtube.com/watch?v=hSS1Ml6YOt8. Nämä olivat vain viimeisimmät, mutta ratkaisua ei löydy. En saa tietokannasta näytettyä dataa. Kello on 20:36.

H.) Name based virtual host

Heti ensimmäisenä löysin lehtorimme sivun: http://terokarvinen.com/2018/name-based-virtual-hosts-on-apache-multiple-websites-to-single-ip-address, jossa kuvataan oikein hyvin tämä konsepti.

Apache2 oli jos asennettu, joten jäljelle jäi ainoastaan:

echo "Default"|sudo tee /var/www/html/index.html

Menin $ cd /var/www/html, jossa oli index.html, jossa oli ainoastaan teksti “Default”. Tein täysin Tero Karvisen ohjeiden mukaan, eli siis loin santeri.siirila.com.conf-tiedoston /etc/apache2/sites-available/santeri.siirila.com.conf, joka näytti tältä:

$ sudoedit /etc/apache2/sites-available/pyora.example.com.conf
$ cat /etc/apache2/sites-available/santeri.siirila.com.conf
<VirtualHost *:80>
 ServerName santeri.siirila.com
 ServerAlias www.santeri.siirila.com
 DocumentRoot /home/xubuntu/publicsites/santeri.siirila.com
 <Directory /home/xubuntu/publicsites/santeri.siirila.com>
   Require all granted
 </Directory>
</VirtualHost>
$ sudo a2ensite santeri.siirila.com
$ sudo systemctl restart apache2

Tein aluksi santeri.siirila.com-sivulle noita asetuksia, mutta kuinka sattuikaan, se oli viety, siispä kesken tehtävän aloin säätää kaikki .com-alkuiset asiat .fi-muotoon. Tämän jälkeen yritin mennä selaimella santeri.siirila.fi, niin tuli ainoastaan error 403 Forbidden. Eli minulla ei olisi tunnuksia. En tiedä, mistä johtuu, mutta selvitellään. Yritin muokata index.html-tiedostoa, mutta mitään ei tapahdu. Siispä, jossain muissa oikeuksissa on virhe. Yritin $ systemctl restart apache2, mutta se ei auttanut ollenkaan.

Olen yrittänyt useita kertoja sivua ‘santeri.siirila.fi’, mutta saan aina vain forbidden 403, virheen. Kun vedin ‘hostname -I’-komennon, niin sain IP-osoitteella yhteyden localhostiin, jossa lukee default. Minun index.html-sivua, jossa on <h1>moi</h1> ei kuitenkaan näy.

Screenshot from 2019-02-02 22-01-56

Testasin luoda index.html-tiedoston minun kotihakemiston public_html kansioon. Loin siihen index.html-tiedoston ja tässä on lopputulos:

Screenshot from 2019-02-02 22-09-52

Tavallaan siis name based virtual hosting toimi, mutta ei kumminkaan root-hakemistossa. Tämä ei ole pääsivulla kuten piti olla, mutta en saa ymmärrettyä, kuinka pitäisi tehdä, kello on 22:11. Lopetan tehtävän toistaiseksi.

F.) Pieni webbiohjelma

Tehtävät ovat enemmän aikaa vieviä kuin oletin, kello on nyt 22:36, joten valitsin tämän. Ehkä nämä lasketaan viideksi tehtäväksi.

Tässä tehtävässä piti tehdä pieni web-ohjelma, kuten vaikka BMI-laiskuri. Siispä etsin aluksi taustatietoa, kuinka tällaisen voisi toteuttaa.

Kopioin aluksi tältä sivulta https://stackoverflow.com/questions/37195181/form-using-function-calculate-bmi-and-display-different-comment-fatal-error-and kaiken index.php-tiedostoon, jonka jälkeen testasin kyseistä kokonaisuutta ja sain 404 Not Found -virhee. Tiedosto yritti uudelleenohjata test.php-tiedostoon, mutta minulla ei sitä ollut, joten piti hieman tutkailla, että mitä sellainen tiedosto edes tarvitsisi sisälleen.

Olen katsonut useita eri lankoja, forumeita ja videoita. Lopulta löysin tämän videon: https://youtu.be/ZdP0KM49IVk. Tämän videon ansiosta sain .php- ja .html-tiedoston oikeaan formaattiin:

bmi.php

<!DOCTYPE HTML> 
<html> 
<head> 
</head> 
<body>
	<?php 
		$weight = $_POST["weight"];
		$height = $_POST["height"];
		$BMI = $weight / ($height * $height);
		print("Your BMI is " + $BMI);
	?>
</body>
</html>

index.html

<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
<form action="bmi.php" method="POST">
<table>
<tr><td>Height in meters</td><td><input type="text" name="height" maxlength="4"></td></tr>
<tr><td>Weight in kilograms</td><td><input type="text" name="weight" maxlength="3"></td></tr>
</table>
<input type="submit" value="Calculate"></input>
</form>
</body>
</html>

Nämä prittasivat sivulle oikeaa formaattia ja laskivat BMI:n oikein. Kello on tehtävän loputtua 0:40.

 

Hienosäätö, Name Based Virtual Host

Kello on 13:15 seuraavana päivänä. Aion yrittää hienosäätää tehtäviä vielä virkeämmällä mielellä. Aloitan DocumentRoot-tehtävästä, jossa piti saada sivu näkymään palvelimen etusivulle ja samalla pitää asettaa muokkausoikeudet normaalille käyttäjälle.

Etsin aluksi hakukoneella apuja ja päädyin tälle sivulle: https://www.dyclassroom.com/howto-ubuntu/how-to-change-document-root-of-apache-on-ubuntu. Tämän dokumentin ansiosta päädyin /etc/apache2-demonin hakemistoon, jossa taas tutkiskelin eilen tekemiäni asioita. Menin tutkimaan /etc/apache2/sites-enabled- ja /etc/apache2/sites-available-hakemistoja, joissa oli erilaisia konfiguraatiotiedostoja. Annoin komennon $ cat santeri.siirila.fi.conf, jotta näkisin, mitä tiedosto sisältää. Siellä luki DocumentRoot /home/santeri/publicsites/santeri.siirila.fi. Yritin antaa sekä hakemistolle, että index.html-tiedostolle oikeuksia komennolla $ chmod -R 777 <tiedosto/hakemisto>. Ei auttanut, sivu antaa edelleen 403 Forbidden -virheilmoitusta. Jatkoin apujen etsimistä ja tämän sivun mukaan https://www.virtualhelp.me/applications/54-web-servers/895-403-forbidden-after-changing-documentroot-directory minun pitäisi muuttaa /etc/apache2/apache2.conf-tiedostoa, joten siis tein niin ja lisäsin siihen rivin

<Directory /home/santeri/publicsites/>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>

Ei siltikään auttanut, vaikka tämän jälkeen käynnistin demonin uusiksi komennolla $ systemctl restart apache2.

Löysin tämän sivun https://stackoverflow.com/questions/6959189/apache-virtualhost-403-forbidden. Siinä neuvotaan laittamaan tällainen litania /etc/apache2/sites-available/santeri.siirila.fi.conf-tiedostoon:

<Directory /home/santeri/publicsites/santeri.siirila.fi>
Order allow, deny
Allow from all
Require all granted
</Directory>

Tämän jälkeen testasin taas uudelleenkäynnistää apache2-demonia, niin sain ilmoituksen

$ systemctl restart apache2
Job for apache2.service failed because the control process exited with error code.
See "systemctl status apache2.service" and "journalctl -xe" for details.

Tein ohjeen mukaan näin:

$ systemctl status apache2.service 
● apache2.service - The Apache HTTP Server
Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Sun 2019-02-03 14:17:42 EET; 3min 12s ago
Process: 7171 ExecStop=/usr/sbin/apachectl stop (code=exited, status=1/FAILURE)
Process: 7213 ExecStart=/usr/sbin/apachectl start (code=exited, status=1/FAILURE)
Main PID: 7139 (code=exited, status=0/SUCCESS)

Tähän ongelmaan auttoi, kun poistin muutokset /etc/apache2/sites-available/santeri.siirila.fi.conf-tiedostosta. Sitten Apache käynnistyi taas normaalisti.

Olen pähkäillyt pari tuntia tämän ongelman äärellä. Ainoaksi ratkaisuksi keksin tähän hätään /public_html-hakemiston. Siispä testaan nyt vaihtaa santeri.siirila.fi-konfiguraatiot siihen polkuun.

Testasin kaikkea, muutin polkuja kahteen eri paikkaan toinen kotihakemiston public_html-kansioon ja toisella kerralla /var/www/html/-hakemistoon. Mikään ei tunnu auttavan, aina saan Forbidden-virhettä. Tältä ihan viimeisimmillään näytti:Screenshot from 2019-02-03 15-40-14

Minun mielestäni tuossa ei ole mitään vikaa, mutta pakko siinä on olla sillä saan aina 403-errorin. Kello on 15:43.

Hienosäätö, LAMP

Menin kotihakemistoni /public_html-kansioon ja poistin kaiken komennolla $ rm -rf * Sen jälkeen tein nanolla nopeasti index.php tiedoston. Tarkoituksena on siis saada ainoastaan tietokanta vuorovaikuttamaan muun ympäristön kanssa. Kello on 15:56.

Olen yrittänyt pähkäillä tätä jo pitkään. Olen testannut muuttaa PHP-koodia ja olen yrittänyt muokata asioita tietokannassa, mutta mikään ei tunnu toimivan. PHP toimii itsessään, mutta en vain saa tietokantayhteyttä toimimaan. Kirjoittamani koodi on otettu lehtorin Tero Karvisen nettisivuilta (http://terokarvinen.com/2018/php-database-select-and-insert-example-php-pdo) ja sitä on muokattu hieman enemmän minulle tarkoituksenmukaiseen muotoon. Se näyttää yrityshetkellä tältä:

<!doctype html>
<html>
<head>
</head>
<body>
<h1>animals</h1>
<?php
$user='testi';
$password='Ku1v4hk0123#"!';
$database='test';
$dsn="mysql:host=localhost;charset=UTF8;dbname=test";
// Open Connection, create new object of PDO class
$pdo=new PDO($dsn, $user, $password);
// Perform SQL Query
$pdoStatement=$pdo->prepare('SELECT * FROM animals;');
$pdoStatement->execute();
$hits=$pdoStatement->fetchAll();
// Print the $hits Array
foreach($hits as $row) {
echo "<p>".$row['id']." ".$row['name']."\n";
}
?>
<h2>testi</h2>
</body>
</html>

Tietokannassa yritin antaa kommennon GRANT ALL PRIVILEGES ON test TO testi@localhost IDENTIFIED BY ‘Ku1v4hk0123#”!’, mutta sekään ei auttanut. Kun hain käyttäjät kannasta ja katsoin heidän oikeudet, niin näytti tältä:

Screenshot from 2019-02-03 21-08-13.png

Joko tämä ongelma on tietokantayhteydessä tai sitten se on käyttäjäoikeuksissa, mutta en vain saa keksittyä vastausta. Olen lukenut todella monia eri lähteitä läpi, mutta yksikään ei oikein tuntunut auttavan minua. Hiominen jää siis hieman huonoon asemaan. Aikaa meni noin kaksi tuntia.

Loppumietteet

Tehtävät olivat paljon haastavampia ja vievät käsittämättömän määrän aikaa. En viitsi edes yrittää enää Apache mod WSGI, PostgreSQL ja Python Flask -yhdistelmän hiomista, sillä siinäkin se ongelma oli juuri tietokantayhteydessä. Ehkä opin jatkossa yhdistämään kannan ja saisin jopa nämä tehtävät paremmin tehtyä. Tästä jatketaan kokemuksia rikkaampina. Kokonaisaika näihin tehtäviin on käytetty ollut noin 20 tuntia. Ehkä hieman alle.