🧑💻 Setting up a new VPS for Django
I've done this a few times and taking this one to go a bit slower and clean up some notes.
Create the VPS instance
- Pick the size and operating system
- Add an SSH key
- Assign an IP to the server and write it down
Set up an SSH alias on local computer
Execute nano ~/.ssh/config
In the file, add the following:
Host mysite
HostName 123.12.12.1234
User myuser
Save and now you'll be able to ssh in with ssh myuser@mysite
instead of ssh [email protected]
Login and update the instance
sudo apt-get update
sudo apt-get upgrade
sudo apt-get full-upgrade
sudo apt-get autoremove
Install and set up UFW firewall
Install:
# Install ufw
sudo apt intall ufw
# Allow ssh
sudo ufw allow ssh
# Enable ufw
sudo ufw enable
sudo ufw reload
sudo ufw status
# optional - see a list of ufw apps
sudo ufw app list
Check and update SSH Permissions
# Open the SSH config file
sudo nano /etc/ssh/sshd_config
PasswordAuthentication no
To disable password authentication and require an SSH Key
- PermitRootLogin no
To disable root login (don't do until after setting up an alternate user)
There's a lot more available here in the article How to Harden OpenSSH
Then Restart the ssh service:
sudo systemctl restart sshd
logout
and if you can ssh back in, you didn't lock yourself out!
Set up a non-root user
Create a new user with the adduser
command
adduser myuser
Add the user to the sudo group with
usermod -aG sudo myuser
Copy the SSH key from the root user to your user
Create the folder for your user if it doesn't exist
mkdir /home/myuser/.ssh
Make the directory only executable by the user
chmod 700 /home/myuser/.ssh
Copy the authorized keys to the user
sudo cp /root/.ssh/authorized_keys /home/myuser/.ssh/authorized_keys
Change ownership to the user
sudo chown -R myuser:myuser /home/myuser/.ssh
Make it readable only by the current user
sudo chmod 600 /home/myuser/.ssh/authorized_keys
logout and try to ssh back in with the myuser
user
Install rsync
rsync is very useful for pushing files up to the server.
sudo apt install rsync
Install caddy as a reverse proxy
We'll use this to route requests from the outside world to our static files and Django application. A few nice things about caddy: - Automatic certificates for https - Pretty easy to set up config and nice defaults like routing http to https
Following the stable release installation instructions here: Debian/Ubuntu/Raspbian instructions.
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
Check the status of caddy:
sudo systemctl status caddy
# 'q' to exit
Install golang-migrate
https://github.com/golang-migrate/migrate/blob/master/cmd/migrate/README.md
# Install the migrate CLI tool.
curl -L https://github.com/golang-migrate/migrate/releases/download/v4.16.2/migrate.linux-amd64.tar.gz | tar xvz
mv migrate.linux-amd64 /usr/local/bin/migrate
# Check migrate installation
migrate -version
Allow http & https traffic through UFW
# Allow http & https
sudo ufw allow "WWW Full"
# Enable ufw
sudo ufw reload
sudo ufw status
Serve a test page from Caddy
# Edit the caddy file
sudo nano /etc/caddy/Caddyfile
Add...
{
auto_https off
}
:80 {
respond "hello world"
}
Restart Caddy and check the status
sudo systemctl restart caddy
sudo systemctl status caddy
In another terminal, use curl to test if it's working:
> curl server.ip.addres.here
hello world
Install Docker
Docker install using the repository
# Add Docker's official GPG key:
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/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# Add the repository to Apt sources:
echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
Install the Docker Packages
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Verify installation is successful by running the hello-world
image
sudo docker run hello-world
Post Docker Installation Configuration
Manage Docker as a non-root user
# Create a docker group
sudo groupadd docker
# Add your user to the group (admin as the default for a lightsail container)
sudo usermod -aG docker $USER
# Logout then log back in
# Verify you can run `docker` commands without `sudo`
docker run hello-world
Configure docker to start on boot with systemd
sudo systemctl enable docker.service
sudo systemctl enable containerd.service
To stop this behavior, use disable
instead
sudo systemctl disable docker.service
sudo systemctl disable containerd.service
Consider a sudo reboot now
to restart the VPS and verify all the services we just set up are running. Replace enable/disable
with status
to check them.
sudo systemctl disable docker.service
sudo systemctl disable containerd.service
Configure the local docker logging driver to rotate logs
Edit the daemon.json
file:
sudo nano /etc/docker/daemon.json
Add the following:
{
"log-driver": "local",
"log-opts": {
"max-size": "10m"
}
}
Serve a Django site from Caddy
sglmr.com {
handle_path /media/* {
root * /var/www/dg-media
file_server
}
handle_path /static/* {
root * /var/www/dg-static
file_server {
precompressed br gzip
}
}
handle {
reverse_proxy 127.0.0.1:8000
}
}
Install redis server for task queues and caching
Not needed if using redis through docker
Install redis to use as a task queue and cache for Django.
sudo apt install redis-server
Open the config file
sudo nano /etc/redis/redis.conf
Change the supervised setting to systemd
# change the supervised setting to `systemd`
supervised systemd
# uncomment the `save` setting to "" to disable persistence
# and also make sure appendonly is set to no
save ""
appendonly no
Restart redis to make sure the settings take effect:
sudo systemctl restart redis.service
Make sure redis is running:
sudo systemctl status redis
Test Redis
Open up the redis cli
redis-cli
ping
and you should get a response PONG
Try adding a test record set test "Hello redis!"
. You should get an OK
response.
Try to retrieve the value with get test
. You should get the same Hello redis!
message back.
Type exit
to exit.
If trying to disable persistence, then we'll want to test that to. Restart your machine with sudo reboot now
.
SSH back into the server. Check the redis status again
sudo systemctl status redis
Go back into the redis-cli
redis-cli
Try to get your test record again with get test
. The response should be (nil)
.
We can also double check the config settings by using config get save
and config get appendonly