diff --git a/Documentation/After installation steps.md b/Documentation/After installation steps.md new file mode 100644 index 0000000..0ad1b33 --- /dev/null +++ b/Documentation/After installation steps.md @@ -0,0 +1,297 @@ +# After installation steps + +When you are done installing Ask @lvkaszus! Project, please follow those steps accordingly to expose this application to world-wide web! + +⚠️ WARNING! You will need a domain name and a valid SSL/TLS certificate for it! ⚠️ + +⚠️ Otherwise, your Anonymous Q&A application will mostly not work because connections to the API Endpoints are with `https://` prefix in application source code and also the Cookies created on Admin Panel page that are stored inside client's browser are with `Secure=True` argument that works only with HTTPS websites! + + +## Prerequisites + +You must have installed all the components from Main installation guide available in `Installation.md` file. If you didn't install anything from there, those instructions will be non-sense to you and your server. + + +If you didn't opened HTTP and HTTPS ports for incoming traffic to your application server, DO THIS NOW! - If you won't do this, you will have problems with accessing your Anonymous Q&A App instance. + + +- Open ports `80` and `443` to enable HTTP and HTTPS on your server. For example if you are using FirewallD as your firewall, just use those commands on your server: + +``` +sudo firewall-cmd --zone=public --permanent --add-port=80/tcp +sudo firewall-cmd --zone=public --permanent --add-port=443/tcp +sudo firewall-cmd --reload +``` + + +# Expose your instance to world-wide web! + +Exposing your instance is mandatory step to allow receiving anonymous questions from people or your friends, and also to manage your installed instance! Scroll down to see how to configure NGINX as a Reverse Proxy for Docker or Non-Docker Instance. + +## Install and configure NGINX as a Reverse Proxy + +### NGINX - for Docker Instance + +- If you not installed NGINX binary on your server yet, install it by using this command (I am using Ubuntu and APT Package Manager, edit this command to match your Linux distribution Package Manager): + +⚠️ WARNING! You can also use NGINX in Docker if you want and use it that way. My personal choice is NGINX Non-Docker + Apps in Docker. ⚠️ + +`sudo apt install nginx` + +- Enable NGINX if it isn't running: + +`sudo systemctl enable --now nginx` + +- Import your SSL/TLS Certificate files to directory that you would like to use by using SFTP connection or by pasting `.pem` and `.key` file contents to your favourite text editor and save those as `.pem` and `.key` files to use them inside NGINX Configuration files. + +- Configure NGINX to serve your Backend API Endpoints and also your Main Frontend and Admin Panel by using your preferred text editor: + +`sudo nano /etc/nginx/sites-available/asklvkaszus-stack` + +- Paste this NGINX Example Configuration file contents below to your new `asklvkaszus-stack` configuration file and change some entries to match your needs: + +``` +# Ask @lvkaszus! - Docker NGINX Configuration Stack: + +server { + listen 80; + listen [::]:80; + listen 443 ssl http2; + listen [::]:443 ssl http2; + + server_name YOUR_MAIN_FRONTEND_DOMAIN_NAME; # Must be same that is set in Backend because of CORS! + + ssl_certificate YOUR_CERTIFICATE_FILE_PATH; # Example: /etc/ssl/my_domain_tls_cert.pem + ssl_certificate_key YOUR_CERTIFICATE_KEY_FILE_PATH; # Example: /etc/ssl/my_domain_tls_cert_key.key + + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers on; + ssl_ciphers "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305"; + ssl_ecdh_curve secp384r1; + ssl_session_timeout 10m; + ssl_session_cache shared:SSL:10m; + ssl_session_tickets off; + ssl_stapling on; + ssl_stapling_verify on; + + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; + add_header X-Frame-Options "SAMEORIGIN"; + add_header X-Content-Type-Options nosniff; + add_header X-XSS-Protection "1; mode=block"; + + server_tokens off; + + location /api/ { + proxy_pass http://127.0.0.1:3030; # If you changed Backend port during container configuration, please update it! + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header Host $host; + proxy_http_version 1.1; + proxy_set_header Connection ""; + + # Needed headers to make Q&A working + proxy_set_header Question $http_question; + proxy_set_header Authorization $http_authorization; + proxy_set_header Answer $http_answer; + } + + location / { + proxy_pass http://127.0.0.1:3031; # If you changed Frontend port during container configuration, please update it! + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header Host $host; + proxy_http_version 1.1; + proxy_set_header Connection ""; + } + + if ($https = '') { return 301 https://$host$request_uri; } +} + +server { + listen 80; + listen [::]:80; + listen 443 ssl http2; + listen [::]:443 ssl http2; + + server_name YOUR_ADMIN_FRONTEND_DOMAIN_NAME; # Must be same that is set in Backend because of CORS! + + ssl_certificate YOUR_CERTIFICATE_FILE_PATH; # Example: /etc/ssl/my_domain_tls_cert.pem + ssl_certificate_key YOUR_CERTIFICATE_KEY_FILE_PATH; # Example: /etc/ssl/my_domain_tls_cert_key.key + + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers on; + ssl_ciphers "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305"; + ssl_ecdh_curve secp384r1; + ssl_session_timeout 10m; + ssl_session_cache shared:SSL:10m; + ssl_session_tickets off; + ssl_stapling on; + ssl_stapling_verify on; + + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; + add_header X-Frame-Options "SAMEORIGIN"; + add_header X-Content-Type-Options nosniff; + add_header X-XSS-Protection "1; mode=block"; + + server_tokens off; + + location / { + proxy_pass http://127.0.0.1:3032; # If you changed Admin Panel port during container configuration, please update it! + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header Host $host; + proxy_http_version 1.1; + proxy_set_header Connection ""; + } + + if ($https = '') { return 301 https://$host$request_uri; } +} +``` + +- Save the file and exit your text editor. Create symlink from `sites-available` to `sites-enabled` folder to make this configuration file enabled inside NGINX: + +`sudo ln -sf /etc/nginx/sites-available/asklvkaszus-stack /etc/nginx/sites-enabled/asklvkaszus-stack` + +- Check your configuration file for errors: + +`sudo nginx -t` + +- If you see `nginx: the configuration file [...] syntax is ok` message on your screen, you can restart your NGINX server by running this command: + +`sudo service nginx restart` + +- Your App should be now available when you visit your domain name where you wanted to install this project! If everything works correctly, then congratulations - You Made It! + + +#### You experienced problems after installation process? + +If you experienced any problems after the installation, open and read `Common problems after installation.md` file for further help! + +### NGINX - for Non-Docker Instance + +- If you not installed NGINX binary on your server yet, install it by using this command (I am using Ubuntu and APT Package Manager, edit this command to match your Linux distribution Package Manager): + +`sudo apt install nginx` + +- Enable NGINX if it isn't running: + +`sudo systemctl enable --now nginx` + +- Import your SSL/TLS Certificate files to directory that you would like to use by using SFTP connection or by pasting `.pem` and `.key` file contents to your favourite text editor and save those as `.pem` and `.key` files to use them inside NGINX Configuration files. + +- Configure NGINX to serve your Backend API Endpoints and also your Main Frontend and Admin Panel by using your preferred text editor: + +`sudo nano /etc/nginx/sites-available/asklvkaszus-stack` + +- Paste this NGINX Example Configuration file contents below to your new `asklvkaszus-stack` configuration file and change some entries to match your needs: + +``` +# Ask @lvkaszus! - Non-Docker NGINX Configuration Stack: + +server { + listen 80; + listen [::]:80; + listen 443 ssl http2; + listen [::]:443 ssl http2; + + server_name YOUR_MAIN_FRONTEND_DOMAIN_NAME; # Must be same that is inside asklvkaszus-backend.py file because of CORS! + + ssl_certificate YOUR_CERTIFICATE_FILE_PATH; # Example: /etc/ssl/my_domain_tls_cert.pem + ssl_certificate_key YOUR_CERTIFICATE_KEY_FILE_PATH; # Example: /etc/ssl/my_domain_tls_cert_key.key + + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers on; + ssl_ciphers "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305"; + ssl_ecdh_curve secp384r1; + ssl_session_timeout 10m; + ssl_session_cache shared:SSL:10m; + ssl_session_tickets off; + ssl_stapling on; + ssl_stapling_verify on; + + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; + add_header X-Frame-Options "SAMEORIGIN"; + add_header X-Content-Type-Options nosniff; + add_header X-XSS-Protection "1; mode=block"; + + server_tokens off; + + location /api/ { + proxy_pass http://127.0.0.1:3030; # If you changed Backend port in gunicorn_config.py file, please update it! + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header Host $host; + proxy_http_version 1.1; + proxy_set_header Connection ""; + + # Needed headers to make Q&A working + proxy_set_header Question $http_question; + proxy_set_header Authorization $http_authorization; + proxy_set_header Answer $http_answer; + } + + location / { + root /var/www/asklvkaszus-frontend; # If you specified other directory than this while installing Frontend, please update it! + index index.html + } + + if ($https = '') { return 301 https://$host$request_uri; } +} + +server { + listen 80; + listen [::]:80; + listen 443 ssl http2; + listen [::]:443 ssl http2; + + server_name YOUR_ADMIN_FRONTEND_DOMAIN_NAME; # Must be same that is inside asklvkaszus-backend.py file because of CORS! + + ssl_certificate YOUR_CERTIFICATE_FILE_PATH; # Example: /etc/ssl/my_domain_tls_cert.pem + ssl_certificate_key YOUR_CERTIFICATE_KEY_FILE_PATH; # Example: /etc/ssl/my_domain_tls_cert_key.key + + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers on; + ssl_ciphers "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305"; + ssl_ecdh_curve secp384r1; + ssl_session_timeout 10m; + ssl_session_cache shared:SSL:10m; + ssl_session_tickets off; + ssl_stapling on; + ssl_stapling_verify on; + + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; + add_header X-Frame-Options "SAMEORIGIN"; + add_header X-Content-Type-Options nosniff; + add_header X-XSS-Protection "1; mode=block"; + + server_tokens off; + + location / { + root /var/www/asklvkaszus-admin; # If you specified other directory than this while installing Admin Panel, please update it! + index index.html; + } + + if ($https = '') { return 301 https://$host$request_uri; } +} +``` + +- Save the file and exit your text editor. Create symlink from `sites-available` to `sites-enabled` folder to make this configuration file enabled inside NGINX: + +`sudo ln -sf /etc/nginx/sites-available/asklvkaszus-stack /etc/nginx/sites-enabled/asklvkaszus-stack` + +- Check your configuration file for errors: + +`sudo nginx -t` + +- If you see `nginx: the configuration file [...] syntax is ok` message on your screen, you must fix permissions for your Frontend and Admin Panel static files: + +``` +sudo chown -R www-data:www-data /var/www/asklvkaszus-frontend # If you specified other directory than this while installing Frontend, please update it! +sudo chown -R www-data:www-data /var/www/asklvkaszus-admin # If you specified other directory than this while installing Admin Panel, please update it! +``` +- Finally, restart your NGINX server by running this command: + +`sudo service nginx restart` + +- Your App should be now available when you visit your domain name where you wanted to install this project! If everything works correctly, then congratulations - You Made It! + + +#### You experienced problems after installation process? + +If you experienced any problems after the installation, open and read `Common problems after installation.md` file for further help! \ No newline at end of file diff --git a/Documentation/Common problems after installation.md b/Documentation/Common problems after installation.md new file mode 100644 index 0000000..d5067b9 --- /dev/null +++ b/Documentation/Common problems after installation.md @@ -0,0 +1,22 @@ +# Common problems after installation + +If you experienced any problems after installation and configuration of my project. Check out those possible fixes for you below before opening a new issue on GitHub! + +This list will be updated regularly when I will get a new issue about this app, and it will be easy to fix. + +### Can't connect to MySQL server on 'xxx:3306' + +This error will be displayed inside logs of GUnicorn server or in the output of the terminal itself, and it is coming from Ask @lvkaszus! Backend side - where questions and answers are handled on the application server. + +Example of this error will look like this: +- `mysql.connector.errors.DatabaseError: 2003 (HY000): Can't connect to MySQL server on 'localhost:3306' (61)` + + +That means that Backend side written in Python can't connect to your questions and answers database, where it will put all of your Q&A data. + +How can I fix this? + +You can fix this, by double-checking the database hostname or IP address that you provided when installing this application. Check if it is correct and not have maybe typo somewhere. If you are used Non-Docker installation method, try replacing your current MySQL Host inside Backend source code file and inside `# BEGIN CONFIGURATION` and `# END CONFIGURATION` there will be a `host='',` line. Try entering there `localhost` or when localhost is not working, try your local IP like `192.168.1.50`. + +But if you was using Docker installation method to install this application, you not missed anything and fixes that I provided above are not working, check if all of the containers are on the same network or create new Docker network and deploy all of the needed containers again but with newly created network attached to all of them. If this doesn't work, you can try typing inside `MYSQL_HOST` environment variable in `asklvkaszus-backend` container a correct name of the MariaDB (or other database server) container like `asklvkaszusdatabase`. + diff --git a/Documentation/Features inside this application!.md b/Documentation/Features inside this application!.md new file mode 100644 index 0000000..654ce96 --- /dev/null +++ b/Documentation/Features inside this application!.md @@ -0,0 +1,51 @@ +# BBCode Integration + +"Ask @lvkaszus!" Project has built-in BBCode support that can format text inside questions and answers. This is done temporarily (for now) by using regular expressions and placing HTML Code inside elements using `dangerouslySetInnerHTML` in React and sanitizing input in Python backend. All done by myself - I was trying to find a suitable library for this, but `react-bbcode` or other libraries like this we're not working in my project 😢 + +This is not a good idea for long-term usage, but in the next release - I will replace this with `BBob` React library thanks to my friend from school named @Bazyli12 for providing me a nice template for using this library inside React projects! ❤️ + +## What is BBCode? + +BBCode is an easy way to format text such as underlining, bolding or italicizing and allows in this project to insert YouTube videos and map locations in the form of geographic coordinates. Also there is automatic URL detection system in questions sent by people using your application based on this project! + +For example: +- Paste any URL to question form or reply form and when the question or answer has been sent, it automatically transforms this URL it into clickable link in user interface. + +## What BBCodes are supported? + +There are several BBCodes supported in this app: + +- `[b]Bold Text[/b]` - Makes the text in the question that is in the [b] and [/b] tags bold like this: Bold text! + +- `[u]Underlined Text[/u]` - Makes the text in the question that is in the [u] and [/u] tags underlined like this: Underlined Text! + +- `[i]Italicized text[/i]` - Makes the text in the question that is in the [u] and [/u] tags italicized like this: Italicized Text! + +Special BBCodes: + +- `[yt]Link to YouTube video[/yt]` - Inserts a YouTube video in the question that is in the [yt] and [/yt] tags. You can check it yourself by self-hosting this project on your own and having fun with it! + +- `[location:Latitude,Longtitude]` - Inserts a location on map by specifying latitude and longtitude in the [location] tag. You can also check it by yourself when self-hosting this project on your own and having fun with it! + +## How to use them inside questions and answers? + +It's pretty easy to use them inside your questions and/or answers! Just type your question or answer like you would do it normally, but type additional things in question/reply form like this: + +- `This is a question with [b]bold text inside![/b]` + + It will look like this after submitting: This is a question with bold text inside! + +## And how to use Special BBCodes like YouTube video embed or map location? + +You also write your question or answer like you would normally do, but with `[yt]Link to YouTube Video[/yt]` tags inside! + +- `Check out this new video! [yt]https://youtube.com/watch?v=ABCD1234[/yt]` + + This will send your question or answer like a normal message but with YouTube Player that plays your video under submitted question/answer! + + +Using Map Location is also straight-forward! Just get your selected location latitude and longtitude numbers from the Internet and write your question/answer just like this: + +- `Check out this place! [location:52.237049,21.017532]` + + This will send your question or answer like a normal message but with location on OpenStreetMaps that shows city of Warsaw in Poland! \ No newline at end of file diff --git a/Documentation/Installation.md b/Documentation/Installation.md new file mode 100644 index 0000000..b8da652 --- /dev/null +++ b/Documentation/Installation.md @@ -0,0 +1,542 @@ +# Installation Guides + +If you want to install this project on your own server as Docker Containers, scroll down to Docker section below! +
+But if you don't want to use Docker for this project, there is also a Manual Installation section below! + +### Prerequisites + +- Get a domain name and a server with Linux installed on it. For free, you can get a server using Oracle Cloud and get up to 4 cores and 24GB of RAM to use on ARM64 architecture (overkill for this project, but if you want to deploy some other applications than that, it can be useful!) + +- Point your domain name to your server by editing DNS records in your domain registrar. You can use Cloudflare DNS for this. If you want to use Cloudflare, you must change the NS records in your domain registrar pointing to Cloudflare (NS1: xxxxx.ns.cloudflare.com NS2: xxxxx.ns.cloudflare.com) and then change the main DNS records (A, CNAME etc.) in Cloudflare Dashboard to point to your server. You also will get free SSL/TLS certificate for your domain. + +- Open ports `80` and `443` to enable HTTP and HTTPS on your server. For example if you are using FirewallD as your firewall, just use those commands on your server: + +``` +sudo firewall-cmd --zone=public --permanent --add-port=80/tcp +sudo firewall-cmd --zone=public --permanent --add-port=443/tcp +sudo firewall-cmd --reload +``` + +## Docker + +You have two ways to deploy this project on your own server. You can use Docker Compose, or deployment by Docker CLI - choose way that you like. + +### Docker Compose + +- Install Docker Compose if you didn't did this previously: + +`sudo apt install docker-compose` + +- Create new Docker Compose file, using this command: + +`nano docker-compose.yml` + +- Paste this to your new Docker Compose file: + +⚠️ WARNING! Modify Environment Variables, Credentials and Domain Names/URLs accordingly! ⚠️ + +``` +version: '3.8' + +services: + asklvkaszusdatabase: + image: mariadb:latest + container_name: asklvkaszusdatabase + networks: + - asklvkaszus-network + environment: + MYSQL_USER: asklvkaszus + MYSQL_PASSWORD: changemeplease + MYSQL_ROOT_PASSWORD: changemeplease + MYSQL_DATABASE: asklvkaszus + restart: unless-stopped + ports: + - "3306:3306" + + asklvkaszusredis: + image: redis:latest + container_name: asklvkaszusredis + networks: + - asklvkaszus-network + restart: unless-stopped + ports: + - "6379:6379" + + asklvkaszusbackend: + image: lvkaszus/asklvkaszus-backend:latest + container_name: asklvkaszusbackend + networks: + - asklvkaszus-network + environment: + MAIN_ACCESS_URL: "ask.example.com" + ADMIN_ACCESS_URL: "admin-ask.example.com" + SENDMSG_LIMIT: "10 per hour" + ADMIN_LIMIT: "50 per hour" + AUTH_KEY: "changeme" + MYSQL_HOST: "asklvkaszusdatabase" + MYSQL_PORT: "3306" + MYSQL_USER: "asklvkaszus" + MYSQL_PASSWORD: "admin" + MYSQL_DATABASE: "asklvkaszus" + REDIS_HOST: "asklvkaszusredis" + REDIS_PORT: "6379" + REDIS_DBS_0: "0" + REDIS_DBS_1: "1" + restart: unless-stopped + ports: + - "3030:3030" + + asklvkaszusfrontend: + image: lvkaszus/asklvkaszus-frontend:latest + container_name: asklvkaszusfrontend + networks: + - asklvkaszus-network + environment: + YOUR_NICKNAME: "@YourNickname" + API_DOMAIN_NAME: "ask.example.com" + restart: unless-stopped + ports: + - "3031:3031" + + asklvkaszusadmin: + image: lvkaszus/asklvkaszus-admin:latest + container_name: asklvkaszusadmin + networks: + - asklvkaszus-network + environment: + YOUR_NICKNAME: "@YourNickname" + restart: unless-stopped + ports: + - "3032:3032" + +networks: + asklvkaszus-network: + driver: bridge +``` + +- If you are done editing your Docker Compose file, just save it and deploy this application by using this command: + +`docker-compose up -d` + +- You are pretty much done! Check if application is running correctly by visiting Main Domain of your application and also Administrator Panel using second Domain Name you just configured! + +### Docker CLI + +- Let's start by downloading and installing Docker Engine on your own server. You can do this by following those simple steps: Just enter this commands below to your server when you are connected to it via SSH. + +(Source: Docker Engine Installation Guide) +``` +sudo apt-get update && sudo apt-get install ca-certificates curl gnupg +sudo install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg +sudo chmod a+r /etc/apt/keyrings/docker.gpg + +echo \ + "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ + "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \ + sudo tee /etc/apt/sources.list.d/docker.list > /dev/null + +sudo apt-get update + +sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin +``` + +- When you are done installing Docker Engine, enable and start Docker Engine (in case it it not enabled yet): + +`sudo systemctl enable --now docker` + +- Add your user to `docker` group to execute commands as non-root user: + +`sudo usermod -aG docker YOUR_USERNAME` + +- Log out and log in back into the server to apply group permissions changes. + +- You are ready to deploy "Ask @lvkaszus!" project onto your server! Let's start with something simple. + +- Not required but recommended: Create separate Docker Network for this project: + +`docker network create asklvkaszus-network` - You can customize network name to fit your needs. + +⚠️ WARNING! Remember your Docker Network name because you will need it to deploy needed containers inside this network with `--network YOUR_NETWORK_NAME` parameter when deploying every single container! ⚠️ +

+### Backend in Docker + +⚠️ WARNING! Pay attention to the commands from now to not make any mistake while deployment process! ⚠️ +

+- We are ready to deploy fresh MariaDB database image from Docker Hub registry using: + +`docker run -d --name asklvkaszusdatabase --network asklvkaszus-network -e MYSQL_USER=asklvkaszus -e MYSQL_PASSWORD=changemeplease -e MYSQL_ROOT_PASSWORD=changemeplease -e MYSQL_DATABASE=asklvkaszus --restart unless-stopped -p 3306:3306 mariadb:latest` + +Short explanation: +
+`MYSQL_USER=asklvkaszus` - Please enter there your main database user that your backend will use. +
+`MYSQL_PASSWORD=changemeplease` - Please change this default password and replace it by strong password that backend will use to access application database. +
+`MYSQL_ROOT_PASSWORD=changemeplease` - Please change this default password and replace it by strong password that is for administrative purposes. +
+`MYSQL_DATABASE=asklvkaszus` - You can modify database name used by this project, but you can also leave it default name. +

+`-p 3306:3306` - Specify the port that MariaDB should be accessible from. Do not change the numbers after the `:`! +

+- Docker Engine should start pulling images from Docker Hub repository, just please wait a while and it will be done and running! + +- When MariaDB image and container is running, you can now install Redis on your server: + +`docker run -d --name asklvkaszusredis --network asklvkaszus-network --restart unless-stopped -p 6379:6379 redis:latest` + +Short explanation: +
+`-p 6379:6379` - Please enter there your Redis port number that your backend will use. Do not change the numbers after the `:`! +

+- After you installed MariaDB Database and Redis Server successfully, you can now finally deploy backend container. + +`docker run -d --name asklvkaszusbackend --network asklvkaszus-network -e MAIN_ACCESS_URL="ask.example.com" -e ADMIN_ACCESS_URL="admin-ask.example.com" -e SENDMSG_LIMIT="10 per hour" -e ADMIN_LIMIT="50 per hour" -e AUTH_KEY="changeme" -e MYSQL_HOST=asklvkaszusdatabase -e MYSQL_PORT="3306" -e MYSQL_USER="asklvkaszus" -e MYSQL_PASSWORD="sameasindatabasecontainer" -e MYSQL_DATABASE="asklvkaszus" -e REDIS_HOST="asklvkaszusredis" -e REDIS_PORT="6379" -e REDIS_DBS_0="0" -e REDIS_DBS_1="1" --restart unless-stopped -p 3030:3030 lvkaszus/asklvkaszus-backend:latest` + +Short explanation: +
+`MAIN_ACCESS_URL="ask.example.com"` - Please enter there your main application URL where users will ask you questions. +
+`ADMIN_ACCESS_URL="admin-ask.example.com"` - Please enter there your application URL where you will be logging in for replying or deleting your questions. +

+`SENDMSG_LIMIT="10 per hour"` - How many requests are allowed in what period of time for sending questions? - '10 per hour' is default. +
+`ADMIN_LIMIT="50 per hour"` - How many requests are allowed in what period of time for an administrator? - '50 per hour' is default. +

+`AUTH_KEY="changeme"` - Generate random password with good length (32 characters recommended), this will be used to authenticate you to the API that Admin Page uses. + +
+ +`MYSQL_HOST=asklvkaszusdatabase` - Enter your MariaDB Database Server hostname. You can type your database container name if you want. +
+`MYSQL_PORT="3306"` - Enter your MariaDB Database Server port. If you didn't change MariaDB port, you can leave defaults there. +
+`MYSQL_USER="asklvkaszus"` - Enter your MariaDB User for Backend access. If you didn't change username, you can leave defaults there. +
+`MYSQL_PASSWORD="sameasindatabasecontainer"` - Please change this default password to password that you provided to Backend user when configuring MariaDB Server. +
+`MYSQL_DATABASE="asklvkaszus"` - Enter your Database Name from MariaDB that Backend will use to store your questions and answers. If you didn't change Database Name, you can leave defaults there. + +
+ +`REDIS_HOST="asklvkaszusredis"` - Hostname or IP Address to your Redis Server where rate-limiting and temporary data will be stored. 'asklvkaszusredis' will mostly work. +
+`REDIS_PORT="6379"` - Port number of your Redis Server - 6379 is default. +
+`REDIS_DBS_0="0"` - Database numbers in your Redis Server. Number '0' is for rate-limiting data. +
+`REDIS_DBS_1="1"` - Database numbers in your Redis Server. Number '1' is for temporary data (only for storing generated ID's temporarily for now) + +- And that's should be it for Backend installation and configuration! + +

+ +### Frontend + +- Frontend and also the Admin Panel are pretty easy to setup with Docker. Just pull the image and deploy with one short command: + +`docker run -d --name asklvkaszusfrontend --network asklvkaszus-network -p 3031:3031 -e YOUR_NICKNAME="@YourNickname" -e API_DOMAIN_NAME="ask.example.com" --restart unless-stopped lvkaszus/asklvkaszus-frontend:latest` + +Short explanation: +
+`-p 3031:3031` - Please enter there your port number that your Frontend will use. Do not change the numbers after the `:`! +

+`YOUR_NICKNAME="@YourNickname"` - Please enter your Nickname that you want to be displayed on your questions page! +
+`API_DOMAIN_NAME="ask.example.com"` - Enter there a valid domain name where your Frontend and Application API will be (ask.example.com/api/v1/fetch_all_questions - for example) - currently must be the same! + +

+ +### Admin Panel + +- Last step of this mess! Just pull the image and deploy with one short command: + +`docker run -d --name asklvkaszusadmin --network asklvkaszus-network -p 3032:3032 -e YOUR_NICKNAME="@YourNickname" --restart unless-stopped lvkaszus/asklvkaszus-admin:latest` + +Short explanation: +
+`-p 3032:3032` - Please enter there your port number that your Admin Panel will use. Do not change the numbers after the `:`! +

+`YOUR_NICKNAME="@YourNickname"` - Please enter your Nickname that you want to be displayed on your questions page! + +
+ +#### After installation Steps + +When you are done installing everything above for this project, head out to the `After installation steps.md` file to expose your freshly installed Anonymous Q&A application like this one to your domain name and world-wide web! + + +#### You experienced problems after installation process? + +If you experienced any problems after the installation, open and read `Common problems after Installation.md` file for further help! + + +## Manual Installation + +Follow these steps, when you want to install this application with Frontend and Admin Panel: + +- Install required packages by using this command if you are using APT Package Manager and Ubuntu: + +`sudo apt install -y build-essential libssl-dev libffi-dev python3-dev python3-pip python3-venv mariadb-server redis git` + +- Install Node Version Manager by using this command: + +`curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash` + +- Also, execute commands that are displayed after installation of NVM: + +``` +export NVM_DIR="$HOME/.nvm" +[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm +[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion +``` + +- Install NPM package using: + +`nvm install node` + +- Run MySQL Secure Installation binary provided by MariaDB Package and configure it to your needs by following the instructions displayed on your screen: + +`sudo mysql_secure_installation` + +There are my settings if you don't know what select here: + +``` +Enter current password for root (enter for none): --- + +Switch to unix_socket authentication [Y/n] N --- + +Change the root password? [Y/n] N --- + +Remove anonymous users? [Y/n] Y + +Disallow root login remotely? [Y/n] Y + +Remove test database and access to it? [Y/n] Y + +Reload privilege tables now? [Y/n] Y +``` + +- Create database and `asklvkaszus` user for backend to database communication: + +``` +sudo mysql -u root + + +CREATE DATABASE asklvkaszus; + +CREATE USER 'asklvkaszus'@'localhost' IDENTIFIED BY 'enter_asklvkaszus_user_password_there'; + +GRANT ALL PRIVILEGES ON asklvkaszus.* TO 'asklvkaszus'@'localhost'; + +FLUSH PRIVILEGES; + +EXIT; +``` + +- Clone project repository and enter it's directory by typing this command: + +`git clone https://github.com/lvkaszus/asklvkaszus-react` + +- And from now, you are ready to install core components of this project like Backend, then Frontend and lastly the Admin Panel! + +

+ +- Create Python Virtual Environment for Ask @lvkaszus! Backend and enable it: + +`python3 -m venv asklvkaszus-backend && cd asklvkaszus-backend && source bin/activate` + +- Copy all contents of Non-Docker Backend directory to your created Python Virtual Environment folder: + +`cp asklvkaszus-react/asklvkaszus-backend/nondocker/*.* ` + +- Open `asklvkaszus-backend.py` file with your favourite text editor for example with `nano`: + +`nano asklvkaszus-backend.py` + +- Search for `# ----- BEGINNING OF CONFIGURATION -----` line and modify some things below it: + +
+ +`FRONTEND_HOST = "your-frontend.host"` and `ADMIN_HOST = "your-backend.host"` - Please enter there your Main Frontend URL and Admin Panel URL WITHOUT HTTPS at the beginning. + +
+ +`SENDMSG_LIMIT = "10 per hour"` and `ADMIN_LIMIT = "50 per hour"` - Please set your rate-limiting rules to fit your needs. If you want, you can leave defaults there. + +
+ +`API_KEY = "changeme"` - Your secret API Authentication Key for Authorization by using API or Admin Panel (replying to questions, deleting them etc.) Please change it from 'changeme' and set it to something that has ideally +24 characters. + +
+ +`SQL_HOST = 'localhost'` - Enter your MariaDB Database Server hostname. If you are installing it on the same host, you can leave defaults there. +
+`SQL_PORT = 3306` - Enter your MariaDB Database Server port. If you didn't change MariaDB port, you can leave defaults there. +
+`SQL_USER = 'asklvkaszus'` - Enter your MariaDB User for Backend access. If you didn't change username, you can leave defaults there. +
+`SQL_PASSWORD = 'admin'` - Password of your MySQL/MariaDB User that you provided above. Please change it from 'admin' and set it to something that has ideally +16 characters. +
+`SQL_DATABASE = 'asklvkaszus'` - Enter your Database Name from MariaDB that Backend will use to store your questions and answers. If you didn't change Database Name, you can leave defaults there. + +
+ +`REDIS_HOST = 'localhost'` - Hostname or IP Address to your Redis Server where rate-limiting and temporary data will be stored. 'localhost' is default. +
+`REDIS_PORT = 6379` - Port number of your Redis Server - 6379 is default. +
+`REDIS_DBS = [0, 1]` - Database numbers in your Redis Server. Number '0' is for rate-limiting data, and '1' is for temporary data (only for storing generated ID's temporarily for now) + + +- And that's should be it for configuring Backend. Save the file by pressing `Ctrl+S` and exit the editor by pressing `Ctrl+X`. + +- Install all required dependencies by executing this command inside your created PyEnv for Backend: + +`pip install -r requirements.txt` + +- After done installing dependencies, check if you can run Python Backend without any problems. If you see this, you are good to go! + +``` +python3 asklvkaszus-backend.py + + * Serving Flask app 'asklvkaszus-backend' + * Debug mode: off +WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. + * Running on http://127.0.0.1:5000 +Press CTRL+C to quit +``` + +- Also check if you can run GUnicorn HTTP Server for Backend. You should see something like this: + +``` +gunicorn -c gunicorn_config.py asklvkaszus-backend:app + +[2023-07-30 20:39:19 +0000] [26394] [INFO] Starting gunicorn 21.2.0 +[2023-07-30 20:39:19 +0000] [26394] [INFO] Listening at: http://0.0.0.0:3030 (26394) +[2023-07-30 20:39:19 +0000] [26394] [INFO] Using worker: gthread +[2023-07-30 20:39:19 +0000] [26395] [INFO] Booting worker with pid: 26395 +``` + +- If both of these things are working correcly, then you can create systemd service unit by entering this command: + +`sudo nano /etc/systemd/system/asklvkaszus-backend.service` + +- Paste this contents into this new file: + +``` +[Unit] +Description=Ask @lvkaszus! - Python Flask Backend Service +After=network.target + +[Service] +User=ubuntu +WorkingDirectory=/home//asklvkaszus-backend +Environment="PATH=/home//asklvkaszus-backend/bin" +ExecStart=/home//asklvkaszus-backend/bin/gunicorn -c /home//asklvkaszus-backend/gunicorn_config.py asklvkaszus-backend:app +Restart=always + +[Install] +WantedBy=multi-user.target +``` + +- Refresh systemd services, enable and also start Backend service: + +``` +sudo systemctl daemon-reload +sudo systemctl enable --now asklvkaszus-backend +``` + +- Deactivate Python Virtual Environment: + +`deactivate` + +- And that's should be it for Backend installation and configuration! + +

+ +### Frontend + +- Go to your cloned repository folder and then to Frontend folder, for example: + +`cd ~/asklvkaszus-react/asklvkaszus-frontend` + +- Install required NPM dependencies: + +`npm install` + +- Create new Environment Variable File by using: + +`nano .env` + +- And pasting this to .env file, modify those accordingly: + +``` +VITE_API_DOMAIN_NAME="YourBackendDomainNameWithoutHttpsAtTheBeginning" +VITE_YOUR_NICKNAME="YourNickname" +``` + +- When you are done modifying those variables, save and exit your file editor. + +- Build source files: + +`npm run build` + +- Check if `dist` folder exists by entering `ls` command. If yes, move it to `/var/www/` folder or other that matches your case: + +``` +sudo mkdir /var/www # This is needed if you don't installed Apache2 or NGINX yet or if it does not exists! +sudo mv dist/ /var/www/asklvkaszus-frontend +sudo chown -R www-data:www-data /var/www/asklvkaszus-frontend # You must install Apache2 or NGINX, without it this command may not work! +``` + +- And that's should be it for Frontend installation and configuration! + +

+ +### Admin Panel + +- Go to your cloned repository folder and then to Admin Panel folder, for example: + +`cd ~/asklvkaszus-react/asklvkaszus-admin` + +- Install required NPM dependencies: + +`npm install` + +- Create new Environment Variable File by using: + +`nano .env` + +- And pasting this to .env file, modify those accordingly: + +``` +VITE_YOUR_NICKNAME="YourNickname" +``` + +- When you are done modifying those variables, save and exit your file editor. + +- Build source files: + +`npm run build` + +- Check if `dist` folder exists by entering `ls` command. If yes, move it to `/var/www/` folder or other that matches your case: + +``` +sudo mkdir /var/www # This is needed if you don't installed Apache2 or NGINX yet or if it does not exists! +sudo mv dist/ /var/www/asklvkaszus-admin +sudo chown -R www-data:www-data /var/www/asklvkaszus-admin # You must install Apache2 or NGINX, without it this command may not work! +``` + +- And that's should be it for Admin Panel installation and configuration! + + +#### After installation Steps + +When you are done installing everything above for this project, head out to the `After installation steps.md` file to expose your freshly installed Anonymous Q&A application like this one to your domain name and world-wide web! + + +#### You experienced problems after installation process? + +If you experienced any problems after the installation, open and read `Common problems after installation.md` file for further help! \ No newline at end of file diff --git a/README.md b/README.md index 217a5a7..25b6e14 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,8 @@ -**Big 3.0 Update Info: Much things will change, some useful features will be added and it will be available very soon!** -

-About Upcoming v3.0: -- Completely re-written and re-designed Backend -- `.env` Environment Variable File with generator written in bash for Backend Settings -- Using JSON Body to send and receive data (instead of HTTP Headers) to fix other problems with encoding/decoding when sending messages/displaying current messages -- Sender Blocking based on sender's IP address blacklisting in one of the database tables (IP Addresses of Users around the internet are public after all, so sender's anonymity/privacy has not been lost!) -- Authorization System that consists of Register + Login + Change Password + Logout features working with JSON Web Tokens (JWT) that are stored in cookies with `HttpOnly=True`, `Secure=True` and `SameSite=Strict` parameters for enhanced protection against XSS and other attacks -- Cross-Site Request Forgery (CSRF) Protection by Flask-WTF -- Separate Rate-limiting for Authorization System, User Frontend Endpoints, Admin Frontend Enpoints, User RESTful API Endpoints and Admin RESTful API Endpoints to enhance rate-limiting options customization -- SQLAlchemy instead of pure SQL Queries -- User/Admin Frontend API -- RESTful User/Admin API with option to restrict CORS Access-Control-Allow-Origin header in .env file -- Feature to completely disable/enable turning on application RESTful User/Admin API by changing Global API setting in application global settings -- User Frontend and Admin Frontend are in one package now (because of CSRF Protection issues when User Frontend was on second domain and when Admin Frontend was on some other domain) -- Update Checker -- 'Approve Questions First' Mode -- Added feature to hide/show all questions or hide/show single question -- Telegram Notifications -- Integrated Backend Tools for recovering/changing administrator password, deleting administrator account or restoring factory default settings -- Re-designed User Interface with Material UI library -
-and many more... - -# Ask @lvkaszus! - Python + React +# ⚠️ Important warning! + +Please DO NOT! install this application version (2.xx) on your server anymore because it is replaced with newer version (3.xx)! Downgrading from version 3.xx to version 2.xx is not compatible because of breaking changes inside application structure. Please DO! install latest version of this application to avoid problems and security issues! + +## Ask @lvkaszus! - Python + React - Anonymous questions and answers pretty much like NGL App or Tellonym, with Backend written in Python, very simple user interface, support for i18n and also BBCode! @@ -33,12 +13,12 @@ and many more... ⚠️ WARNING! - You must have domain name and SSL/TLS certificate to use this application without any modifications to the source code! This is needed for your security. ⚠️ -## Why this was created? +### Why this was created? I pretty much like the conception of NGL App or Tellonym, but I didn't like overall application operation. So, I created my own alternative to them with some added features and no analytics inside source code. -## Features +### Features - You can change nickname viewed on Frontend and Backend from "@lvkaszus" to for example "@MyNickname" - Separated Backend, Frontend and Admin Panel @@ -56,31 +36,29 @@ I pretty much like the conception of NGL App or < - Very basic authentication system by using API Auth Key specified by you during installation of Backend of this App and Cookies with expiration time of 30 minutes by default -## Installation +### Installation If you want to deploy this project on your own server, you have two options: - Installing with Docker - Installing without Docker

-Click here to go to Wiki Page for Installation With Docker -

-Click here to go to Wiki Page for Installation Without Docker +Open and read `Installation.md` file in the `Documentation` folder for Installation steps. -## Common problems +### Common problems -If you experience any problems after installation, feel free to visit this Wiki page here! +If you experience any problems after installation, feel free to open and read `Common problems after installation.md` file in the `Documentation` folder! -## Wiki +### Full documentation -There is Wiki Page available for this project! You can read full documentation of this project here. +You can read full documentation of this project in the `Documentation` folder. -## Do you want to contribute? +### Do you want to contribute? If you want to add new feature to this project or improve something, you can contribute without any problems! -## Credits +### Credits - This project uses Python libraries like Flask, Flask-Limiter, Flask-CORS, mysql-connector-python, bleach and others. - This project uses React library. (https://github.com/facebook/react) - This project uses Vite library. (https://github.com/vitejs/vite)