- Intro
- Code Style
- Maintaining the Repo
- Versioning
- Configuring a Database
- Automated tests
- Creating a Local Test Environment
- Recommended Server Setup
- Install nginx and python3
- Install virtual environment to run the python code
- Clone python code
- Start setting up python virtual environment
- Allow port 5000 access
- Download and start MariaDB
- Use your SQL credentials to create the database
- Set up configurations for the server
- Initialize database tables
- Start the server with the following command
- Test that the server responds with a proper response
- Kill the server and test gunicorn with the server
- Test that the server responds with a proper response
- Kill the server and leave the python environment
- Create service to start up gunicorn with wsgi.py
- Start service
- Create Nginx file
- Note, server_name needs to be the name you own
- Link trusat-backend
- Restart and configure the rest of nginx
- Change localhost with the domain name from above
- Create certificate
This repo contains the code for deploying, populating and interacting with a TruSat database and its standard REST API.
The easiest way to test/exercise this code is by creating a trusat-config.yaml file (see below), setting the environmental variables, launching wsgi.py
, and then using the snapshot tests to exercise the API and its underlying database.
This should be a text file containing the parameters of the Database
contructor - with one parameter on each line. At the time of writing that means:
# Trusat Database Connection Configuration
Database:
name: "space"
type:
hostname: "127.0.0.1"
username: "root"
password:
Place the updated file in the parent directory of ./trusat-orbit to avoid commiting your sensitive data to GIT.
API key associated with a mailgun account. Without this, users cannot recover or create an account.
Email address that the mailgun API will use to send emails.
Example:
example@example.com
Desired origins for the website REST API to accept from. This is currently required.
Example:
https://trusat.org,https://www.trusat.org
Secret bytes that will be used for flask security features. This can be generated using the following code:
import os
import base64
random_number = os.urandom(256)
random_number_base64 = base64.b64encode(random_number)
Example:
'ucCWKF7iqBqLNVoa6dS5Bc+mYYTecgcPg3Uv9nPP043hcdLPaE/UhBqqAChdytGifzeKzFl2bT4aN0B5xqEtEvB4CnkJIorgmnVhlrH3m663Fq7Uish32rH57AIeAtlZGo7L0OhYbNRPKewvlK0YfzUQt/I1Iaf/Duxa7SZ19c3cVgkzC9g4fKrhbE2TUXRnjpdFQY2I30SRwt3RYmRQRO2hSvstpIHtn5k3hFu71aQmS2ILFoyijksWyAC0eh4fgxJPmvfaGfexxiyHgAkv9bdWVzcdNeitld/glGJk7G4NquccJFozPqY3UqMg+ZLJzz36abe3gT5Yv/WAxNZlCQ=='
Follow PEP 8 for any Python code and the style guide recommended for any other language.
Style Guide With the addition of commits to the master branch are done through PRs (Pull Request).
Modified from pyorbital
- checkout master
- pull from repo
- run the unittests
- create a tag with the new version number, starting with a 'v'. eg:
git tag v0.1.1 -m "Version 0.1.1
Version Numbering
5. push changes to github git push --follow-tags
7. check verification tools
Configuration of the database endpoint is done in the code that constructs the Database
object in databse.py
. Typically this is configured in flask_server.py
.
You can use this code against our development and production databases at db.consensys.space
(running in Amazon Relational Database Service (RDS), but in some cases, it may be preferable to develop against a local database.
Install and configure mariadb on your local machine, run it and secure it. Instructions for MacOS here
Access mariadb using:
mysql -u root -p
(you will be prompted for your password). Then run
CREATE DATABASE opensatcat_local;
to create a test database.
Optional: create a non-root
user for testing.
To export all (~200MB) data from the RDS database:
mysqldump -h db.consensys.space -u neil.mcclaren -p opensatcat > opensatcat_dump.sql
Replace neil.mcclaren
with your db.consensys.space
user. You will be prompted for a password.
If your user does not have LOCK permissions then you may need to add a --skip-lock-tables
flag, e.g. mysqldump -h db.consensys.space -u neil.mcclaren --skip-lock-tables -p opensatcat > opensatcat_dump.sql
)
From the same directory that you did the export, import the data into your local DB by running:
mysql -u root -p opensatcat_local < opensatcat_dump.sql
These are a work in progress.
Run:
-
Run
pytest
to run some snapshot tests.- These assume you are running an API server on your local machine and that it is pointing at a database identical to (a 2019-09-13 clone of) the "production" database.
- The test makes some API requests, and compares each result to an expected result that's stored in the
snapshots
folder
-
Run
pytest
with a-s
or--durations 50
flag to add timing information to the output -
Run
pytest --snapshot-update
to update the snapshots if either the expected behavior or the underlying data changes.
This requires python3 and yarn/npm (replace any yarn command with npm if applicable)
python3 -m pip install --user virtualenv
git clone https://github.com/TruSat/trusat-orbit
git clone https://github.com/TruSat/trusat-backend
cd trusat-backend
git clone https://github.com/TruSat/trusat-frontend
cd trusat-frontend
yarn install
export REACT_APP_API_ROOT="http://localhost:5000"
yarn build
cd ..
python3 -m virtualenv trusat-backend-env
source trusat-backend-env/bin/activate
pip install wheel gunicorn
pip install -r requirements.txt
pip install -r ../trusat-orbit/requirements.txt
For macOS:
brew install mariadb
mysql.server start
brew services start mariadb
For Ubuntu:
sudo apt update
sudo apt install mariadb-server
sudo systemctl status mariadb
NOTE: If mysql -u root
doesn't work, you may need to use sudo. It is recommended to create a user that is separate from root.
mysql -u root
CREATE DATABASE space DEFAULT CHARACTER SET 'utf8';
Set up the following environmental variables to enable all features
export MAILGUN_API_KEY=''
export MAILGUN_EMAIL_ADDRESS=''
export WEBSITE_ORIGINS='http://localhost'
export SECRET_KEY=''
Add trusat-config.yaml to the parent directory with all the database connection information
# Trusat Database Connection Configuration
Database:
name: "space"
type: "sqlserver"
hostname: "127.0.0.1"
username: "newuser"
password: "user_password"
python create_tables.py
python database_tools/categorize.py
python wsgi.py
if curl http://localhost:5000/heartbeat > HTML_Output
then echo "Request was successful"
else echo "Server did not set up correctly"
fi
(Make sure db accepts inbound of the IP (public and or internal)
Very helpful article on how to run trusat-backend with Nginx and gunicorn. Or feel free to follow the steps below
sudo apt update
sudo apt install nginx
sudo apt install python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools
python3 -m pip install --user virtualenv
git clone https://github.com/TruSat/trusat-orbit
git clone https://github.com/TruSat/trusat-backend
cd trusat-backend
git clone https://github.com/TruSat/trusat-frontend
python3 -m virtualenv trusat-backend-env
source trusat-backend-env/bin/activate
pip install wheel gunicorn
pip install -r requirements.txt
pip install -r ../trusat-orbit/requirements.txt
sudo ufw allow 5000
Download, start, and check MariaDB
sudo apt update
sudo apt install mariadb-server
sudo systemctl status mariadb
NOTE: If mysql -u root
doesn't work, you may need to use sudo. It is recommended to create a user that is separate from root.
mysql -u root
Create the database
CREATE DATABASE space DEFAULT CHARACTER SET 'utf8';
When done, use the exit
command. If you prefer a separate account, use the section below before exiting
CREATE USER 'newuser'@'localhost' IDENTIFIED BY 'user_password';
Select PASSWORD('user_password');
Use the string that is printed, starting with *
, and paste it into the right side of the following command. Decide on the access this user will have or use the last command
SET PASSWORD FOR 'newuser'@'localhost' = '';
GRANT ALL ON *.* to newuser@localhost IDENTIFIED BY 'user_password';
Set up the following environmental variables to enable all features
export MAILGUN_API_KEY=''
export MAILGUN_EMAIL_ADDRESS=''
export WEBSITE_ORIGINS='http://localhost'
export SECRET_KEY=''
Add trusat-config.yaml to the parent directory with all the database connection information
# Trusat Database Connection Configuration
Database:
name: "space"
type: "sqlserver"
hostname: "127.0.0.1"
username: "newuser"
password: "user_password"
(Make sure db accepts inbound of the IP (public and/or internal)
python create_tables.py
python database_tools/categorize.py
python wsgi.py
if curl http://localhost:5000/heartbeat > HTML_Output
then echo "Request was successful"
else echo "Server did not set up correctly"
fi
gunicorn --bind 0.0.0.0:5000 wsgi:app
if curl http://localhost:5000/hearbeat > HTML_Output
then echo "Request successful"
else echo "Server did not set up correctly"
fi
deactivate
Use the following command and modify the file information to work with your system.
sudo vim /etc/systemd/system/trusat-backend.service
Example trusat-backend.service:
[Unit]
Description=Gunicorn instance to serve trusat-backend
After=network.target
[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/trusat-backend
Environment="PATH=/home/ubuntu/trusat-backend/trusat-backend-env/bin"
ExecStart=/home/ubuntu/trusat-backend/trusat-backend-env/bin/gunicorn --workers 4 --bind unix:trusat-backend.sock -m 007 wsgi:app
Environment="SECRET_KEY="
Environment="MAILGUN_API_KEY="
Environment="MAILGUN_EMAIL_ADDRESS="
Environment="WEBSITE_ORIGINS="
[Install]
WantedBy=multi-user.target
sudo systemctl start trusat-backend
sudo systemctl enable trusat-backend
sudo systemctl status trusat-backend
Look for similar output:
ubuntu:~/trusat-backend$ sudo systemctl status trusat-backend
● trusat-backend.service - Gunicorn instance to serve trusat-backend
Loaded: loaded (/etc/systemd/system/trusat-backend.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2020-03-03 21:28:04 UTC; 13s ago
Main PID: 24058 (gunicorn)
Tasks: 5 (limit: 1152)
CGroup: /system.slice/trusat-backend.service
├─24058 /home/ubuntu/trusat-backend/trusat-backend-env/bin/python /home/ubuntu/trusat-backend/trusat-backend-env/bin/gunicorn --workers 4 --bind unix:trusat-backend.sock -m 007 wsgi:app
├─24079 /home/ubuntu/trusat-backend/trusat-backend-env/bin/python /home/ubuntu/trusat-backend/trusat-backend-env/bin/gunicorn --workers 4 --bind unix:trusat-backend.sock -m 007 wsgi:app
├─24080 /home/ubuntu/trusat-backend/trusat-backend-env/bin/python /home/ubuntu/trusat-backend/trusat-backend-env/bin/gunicorn --workers 4 --bind unix:trusat-backend.sock -m 007 wsgi:app
├─24081 /home/ubuntu/trusat-backend/trusat-backend-env/bin/python /home/ubuntu/trusat-backend/trusat-backend-env/bin/gunicorn --workers 4 --bind unix:trusat-backend.sock -m 007 wsgi:app
└─24082 /home/ubuntu/trusat-backend/trusat-backend-env/bin/python /home/ubuntu/trusat-backend/trusat-backend-env/bin/gunicorn --workers 4 --bind unix:trusat-backend.sock -m 007 wsgi:app
Mar 03 21:28:04 systemd[1]: Started Gunicorn instance to serve trusat-backend.
Mar 03 21:28:04 gunicorn[24058]: [2020-03-03 21:28:04 +0000] [24058] [INFO] Starting gunicorn 20.0.4
Mar 03 21:28:04 gunicorn[24058]: [2020-03-03 21:28:04 +0000] [24058] [INFO] Listening at: unix:trusat-backend.sock (24058)
Mar 03 21:28:04 gunicorn[24058]: [2020-03-03 21:28:04 +0000] [24058] [INFO] Using worker: sync
Mar 03 21:28:04 gunicorn[24058]: [2020-03-03 21:28:04 +0000] [24079] [INFO] Booting worker with pid: 24079
Mar 03 21:28:04 gunicorn[24058]: [2020-03-03 21:28:04 +0000] [24080] [INFO] Booting worker with pid: 24080
Mar 03 21:28:04 gunicorn[24058]: [2020-03-03 21:28:04 +0000] [24081] [INFO] Booting worker with pid: 24081
Mar 03 21:28:04 gunicorn[24058]: [2020-03-03 21:28:04 +0000] [24082] [INFO] Booting worker with pid: 24082
sudo vim /etc/nginx/sites-available/trusat-backend
server {
listen 80;
server_name trusat.org www.trusat.org;
location / {
include proxy_params;
proxy_pass http://unix:/home/ubuntu/trusat-backend/trusat-backend.sock;
}
}
sudo ln -s /etc/nginx/sites-available/trusat-backend /etc/nginx/sites-enabled
sudo nginx -t
The test should look similar to below
ubuntu:~/trusat-backend$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
sudo systemctl restart nginx
sudo ufw delete allow 5000
sudo ufw allow 'Nginx Full'
if curl http://localhost/hearbeat > HTML_Output
then echo "Request successful"
else echo "Server did not set up correctly"
fi
Don't forget to create a DNS record
sudo add-apt-repository ppa:certbot/certbot
sudo apt install python-certbot-nginx
sudo certbot --nginx -d trusat.org -d www.trusat.org
sudo ufw delete allow 'Nginx HTTP'