# README # 1. [Installation](#installation) 2. [Running a demo](#running-a-demo) 3. [Troubleshooting](#troubleshooting) --- ## 1. Requirements The webserver is a python application that requires `python3.6` and `pip` to be installed. It's also recommended to install `npm` (Node package management) to install the javascript libraries. ```bash sudo apt install python3 python3-pip npm # debian, ubuntu, mint, ... sudo pkg install python36 py36-sqlite3 py36-pip py36-setuptools npm # FreeBSD ``` The file `~/.config/pip/pip.conf` should be configured to the following: ```ini [global] user=yes [list] format=columns ``` Note: In MacOS this file is in `~/Library/Application Support/pip/pip.conf`. --- ## 2. Installation Download and install: ```bash git clone https://USERNAME@bitbucket.org/USERNAME/perguntations.git pip3 install --user perguntations ``` where `USERNAME` is your account on bitbucket. This will also install any dependencies required to run the software. --- ## 3 Setup The server will run an https server and requires valid certificates. To generate certificates, there are two possibilities: public server with static IP address or a private server on a local network. Certificates must be saved in the `$XDG_DATA_HOME` path if defined in the environment, otherwise in `~/.local/share/certs`. Create the directory if needed: ```bash [ ! -z "$XDG_DATA_HOME" ] || mkdir -p ~/.local/share/certs ``` ### Selfsigned certificates Self-signed certificates are not certified by a recognised authority and browsers will complain that the certificate is not trusted. ```bash cd WHERE/TO/PUT/CERTS openssl req -x509 -newkey rsa:4096 -keyout privkey.pem -out cert.pem -days 365 -nodes ``` ### LetsEncript (FreeBSD) Generating certificates for a public server (FreeBSD) requires a registered domain with fixed IP. ```sh sudo pkg install py27-certbot # FreeBSD sudo service pf stop # disable pf firewall (FreeBSD) sudo certbot certonly --standalone -d www.example.com sudo service pf start # enable pf firewall ``` Certificates are saved in `/usr/local/etc/letsencrypt/live/www.example.com/`. Copy them to the appropriate `certs` directory and change permissions: ```sh chmod 400 cert.pem privkey.pem ``` Certificate renewals can be done as follows: ```sh sudo service pf stop # shutdown firewall sudo certbot renew sudo service pf start # start firewall ``` Again, copy certificate files `privkey.pem` and `cert.pem` to the `certs` directory. --- ## Installing 3rd party javascript libraries The javascript libraries are not included in the repository. The following libraries are currently necessary (as of 24/1/2019): ``` DataTables MDB-Free_4 MathJax-2.7.5 bootstrap-4.2.1-dist codemirror-5.42.2 fontawesome-free-5.6.3-web jquery-3.3.1.min.js popper.min.js ``` Downloaded and install them in the directory perguntations/static/lib. FIXME: use `npm` --- ## Running a demo The directory `demo` includes a demo test that can be used as a template for your own tests and questions. To run the demonstration test you need to initialize the database using one of the following methods: ```.bash ./initdb.py students.csv # initialize from a CSV file ./initdb.py --admin # only adds the administrator account ./initdb.py --add 123 "Asterix Gaules" # add one student # a database file "students.db" is created mv students.db demo/ # create directory to save the finished tests mkdir demo/ans # edit test configuration and check if everything looks right vi demo/test-tutorial.yaml ``` We are now ready to run the server: ```.bash ./serve.py --help # get help ./serve.py demo/test-tutorial.yaml # run demo test ``` By default the server listens on port 8443 and on all IPs of all network interfaces. Open the browser at `http://127.0.0.1:8443/` and login as user number `0` (administrator) and choose any password. Then 1. Authorize students by clicking the checkboxes. 2. Open a different browser at `http://127.0.0.1:8443/` and login as one of the authorized students. Answer the questions and submit. The server can be stoped from the terminal with `^C`. ## Running on lower ports 80 or 443 Ports 80 and 443 are reserved for the root user and and this software _should NOT be run as root_. Instead, the firewall should be configured to forward tcp traffic from port 443 to 8443 where the server is listening. The details depend on the operating system. ### debian: ```.bash iptables -t nat -I PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-ports 8080 FIXME: also for port 443... ``` Explanation: - `-t nat` is the table consulted when a packet creates a new connection. - `-I PREROUTING` inserts rules at the head of the chain. - `-p tcp` selected protocol. - `-s 0/0` source network address/mask. - `-i eth0` interface via which the packet was received. - `--dport 80` destination port. - `-j REDIRECT` what to do when packet matches the rule. - `--to-ports 8080` where to redirect the packets. ### FreeBSD and pf Edit `/etc/pf.conf`: ext_if="em0" rdr on $ext_if proto tcp from any to any port 80 -> 127.0.0.1 port 8080 rdr on $ext_if proto tcp from any to any port 443 -> 127.0.0.1 port 8443 or `ext_if="vtnet0"` for guest additions under virtual box. Start firewall with `sudo service pf start`. Optionally, to activate pf on boot, edit `rc.conf`: pf_enable="YES" pf_flags="" pf_rules="/etc/pf.conf" # optional logging: pflog_enable="YES" pflog_flags="" pflog_logfile="/var/log/pflog" ## Troubleshooting * The server tries to run `python3` so this command must be accessible from user accounts. Currently, the minimum supported python version is 3.6. * If you are getting any `UnicodeEncodeError` type of errors that's because the terminal is not supporting UTF-8. This error may occur when a unicode character is printed to the screen by the server or, when running question generator or correction scripts, a message is piped between the server and the scripts that includes unicode characters. Try running `locale` on the terminal and see if there are any error messages. Solutions: - debian: fix it with `sudo dpkg-reconfigure locales`, select your UTF-8 locales and try again. - FreeBSD: edit `~/.login_conf` to use UTF-8, for example: ``` me:\ :charset=UTF-8:\ :lang=en_US.UTF-8: ``` ## Contribute ### * Writing questions in yaml format * Testing and reporting bugs * Code review * New features and ideas ### Contacts ### * Miguel BarĂ£o mjsb@uevora.pt