This guide will detail a server setup for a web application using the Flask framework. An instance on Amazon's Lightsail is used for hosting - providing a Linux server at a low, fixed cost. This guide covers configuration for:
Software | Purpose |
---|---|
Amazon (AWS) Lightsail instance | Host provider |
Linux / Ubuntu | Operating system |
Nginx | Web server |
Let's Encrypt | SSL certificate |
Supervisor | Manage Gunicorn processes |
Gunicorn | Python WSGI server |
Flask | Python web framework |
- Create an account or login to AWS Lightsail, https://lightsail.aws.amazon.com.
- On the Instances tab, create an Ubuntu 20.x LTS instance (OS Only)
- On the Networking tab, create a static IP address and attach it to your instance.
- On the Instances tab, find the 'Manage' option for your instance and enable HTTPS (port 443) on the 'Networking' tab for both the IPv4 and IPv6 firewalls.
If you will be using a custom domain, set up a blank "A" record with your DNS provider and point it at the static IP address for your instance.
From the Instances tab in the Lightsail web interface, you can start an SSH session from your browser using the "Connect" option. For extra convenience, you can bookmark the URL for the session for your instance (e.g. https://lightsail.aws.amazon.com/ls/remote/us-east-2/instances/instance-name/terminal?protocol=ssh). Alternatively, you can:
- From the Account navigation menu in Lightsail, choose "Account" and then move to the "SSH keys" tab. You'll be able to download a default SSH key from this page.
- Move the key file to the appropriate directory in your system. Depending on your system, you may need to set permissions for the key, e.g.
chmod 400 key.pem
- SSH into the server, e.g.
ssh -i ~/.ssh/key.pem ubuntu@11.111.11.11
If you would like to use a more recent version of Python than what is availble in the Ubuntu LTS instance, you can use the 'deadsnakes' PPA to add a newer version alongside the existing one.
- Install Python 3.11.x:
sudo add-apt-repository ppa:deadsnakes/ppa sudo apt update sudo apt install python3.11 sudo apt-get install python3.11-venv
- Install packages for python, let's encrypt, supervisor, nginx, git:
sudo apt-get -y update
sudo apt-get -y install certbot python3-certbot-nginx
sudo apt-get -y install supervisor nginx git
- Run upgrades with
sudo apt-get upgrade
- You may have to do a couple rounds of updates and reboot in-between,
sudo reboot
- You may have to do a couple rounds of updates and reboot in-between,
- Disallow root login and password logins,
sudo nano /etc/ssh/sshd_config
# set these lines, if not already set PermitRootLogin no PubkeyAuthentication yes PasswordAuthentication no ChallengeResponseAuthentication no
- Restart the SSH service,
sudo service ssh restart
- Remove the default configuration file,
sudo rm /etc/nginx/sites-enabled/default
and create a new onesudo nano /etc/nginx/sites-enabled/appname
:server { listen 80; listen [::]:80; server_name example.com; location / { proxy_pass http://localhost:8000; } access_log /var/log/appname_access.log; error_log /var/log/appname_error.log; client_max_body_size 5M; }
- Check the syntax of the configuration file,
sudo nginx -t
and reload Nginxsudo service nginx reload
- If you haven't already, add a DNS record for your custom domain and point it to your Lightsail instance's static IP
- Run certbot for your domain,
sudo certbot --nginx -d example.com
- Do a dry-run to make sure setup is correct,
sudo certbot renew --dry-run
- Create a supervisor configuration file,
sudo nano /etc/supervisor/conf.d/appname.conf
:[program:appdirectory] command=/home/ubuntu/appdirectory/venv/bin/gunicorn -b localhost:8000 -w 3 appname:app directory=/home/ubuntu/appdirectory user=ubuntu autostart=true autorestart=true stopasgroup=true killasgroup=true
- Configure an SSH key on your Lightsail instance for GitHub clones/pulls:
cd ~/.ssh
ssh-keygen -t ed25519 -C "example@example.com"
- To avoid having to add the key to the ssh-agent, don't give the key a custom name (will default to "id_ed25519"), and (optionally) set a passphrase
- Add the public key as a 'deploy key' to your GitHub repo, e.g. https://github.com/username/reponame/settings/keys
- Checkout application files, create a virtual enviornment and install application dependencies:
cd ~
git clone git@github.com:username/example-repo.git
cd example-repo
python3.11 -m venv venv
source venv/bin/activate
pip3 install -r requirements.txt
- Set configuration variables and setup the database, if necessary, e.g.
flask db upgrade
- Reload supervisor:
sudo supervisorctl reload
sudo supervisorctl status
To make udpates to the application, you can do a git pull
on the repo and then run sudo supervisorctl reload
.
- Create a username and password with Nginx:
sudo sh -c "echo -n 'myusername:' >> /etc/nginx/.htpasswd"
sudo sh -c "openssl passwd -apr1 >> /etc/nginx/.htpasswd"
- Edit your configuration file (e.g.
sudo nano /etc/nginx/sites-enabled/appname
) and add 'auth_basic' lines:... location / { proxy_pass http://localhost:8000; auth_basic "Restricte Content"; auth_basic_user_file /etc/nginx/.htpasswd; } ...
- Check the syntax of the configuration file,
sudo nginx -t
and reload Nginxsudo service nginx reload
- add ufw configuration?
- add database configuration, other flask configuration?