Deploying my Wagtail blog to Digital Ocean, pt. 2

4 Mar 2020

category is ~ python ~ django ~ wagtail ~ digital ocean ~ nginx ~ gunicorn ~

The first part of this post is here.

It’s true what they say: when you reach a goal in programming, that sense of achievement is real. It is something I’d underestimated. Coming from a “creative” background as a writer, creating work you’re proud of is quite a different feeling. Maybe it’s because you know it’s come from you, whereas when you get stuff right in programming, you figured something out; something that millions of people have also had to learn and get their heads around. Writing is lonely, but programming, no matter how much some may insist otherwise, is community-based.

In other words, I was elated when I got my site online. My joy was short-lived — more on that later — but I’m going to publish this post anyway.

4. Testing — and not

This is a topic too broad to cover, so I’m just going to say the entirety of Obey the Testing Goat by Harry Percival is available online for free, for your reference. It walks you through testing Django apps with Selenium.

Confession: I went back on my word and didn’t test this as extensively as I wanted to, as I was kind of in a hurry. Luckily, most stuff worked when the site went live (read on to find out what didn’t). I did have a brush with Geckodriver and I hated it. It’s recommended in the book as the webdriver communicating between Firefox and Selenium, as it was a complete pain to install… however, if you are determined to use Firefox as your browser, it’s kinda the only way. The first time I tried to add Geckodriver as an executable, I ended up breaking my bash console. (By the way, if this ever happens to you, the solution is to open .bash_profile, delete everything, and make sure the path is export PATH=/bin:/usr/bin:/usr/local/bin).

Here is what I ended up doing, with these guides helping me.

Go here and pick your Geckodriver version to download to your local drive; if you’re using a DO server it’ll most likely be geckodriver-v0.26.0-linux64.tar.gz (I spent aaaaages wondering why it wasn’t working, when it turned out I’d been on autopilot and downloaded the MacOS one. Doh!) Unzip the folder and there should be a geckodriver executable file within it.

Go to /usr/local/share on your Ubuntu server and create a directory called geckodriver2 (so that you don’t confuse it with the local one). Connect to FileZilla and move the geckodriver file to geckodriver2.

It’s possible you’ll get the following stack trace error: selenium.common.exceptions.WebDriverException: Message: 'geckodriver' executable may have wrong permissions. This probably means you’ll need to change the PATH in the .bash_profile file (Google will help you find it). After doing so, run source .bash_profile so the changes are applied, then test that it worked by running echo $PATH.

I’ve played around with Selenium within the context of parsing HTML, but I certainly have more to learn when it comes to testing. Also, the Selenium “language” is called Selenese, which sounds nice!

That’s all I have to say about testing for now!

5. Security

When everything is ready, don’t open the golden gates (port 80) to internet traffic yet!!! First, run python manage.py check --deploy. This will give you an automated list of security issues you need to rectify before you deploy.

Django offers its own deployment checklist, or you can refer to this more beginner-friendly one, which spells out some of the security warnings you will see when you run the command above. Among other warnings, I solved W004, W006, W007, and W008 thanks to this guide. I also found that some issues with static and styling could be solved by clearing the browser cache.

There’s also the perennial question of how to deal with secret info in Django projects, such as database credentials and the SECRET_KEY. I made sure I had all info common to development and production in base.py, while private info was in dev.py, which in turn was listed in the .gitignore. The “public version” with concealed info, which runs in production, is therefore in production.py.

Again, virtual environments are a whole ‘nother topic, so I’ll just say I used the environ library. Docs here.

6. Deployment

Now that your security settings are hopefully watertight, make sure you set DEBUG = False in your production.py file! This is like the code version of having lipstick on your teeth, only significantly more dangerous in terms of privacy and security.

Since I had been working on a VM but had done the bulk of the actual site creation on my local machine, I had to generate another SSH key so I could commit my project to GitHub. I ended up creating a new repo for the stuff I’d been doing on the VM, as I wanted to to keep it separate from the work I’d done which was mainly “design”-related.

After setting the DNS records for my desired domain on Digital Ocean, the next step was getting an SSL certificate — I used Certbot, which is free (be sure to select the right system!). Then, as the DO documentation says, I did sudo ufw delete allow 8000 then sudo ufw allow 'Nginx Full' to close the development server port and open port 80.

And then the website was online at rosederwelt.com, and it was good. For a while there, I didn’t think that day would come!

7. Work in progress

Alas, I sabotaged myself when I tried fixing something. When editing a page in the Wagtail admin and previewing it, I got a 400 error. I started to fix this by going in to the panel on the left-hand side of the admin page, clicking onSettings, then Sites.

From there, click on localhost with port 80. Change the number of the port. Also, I don’t think it’s mandatory, but I also just changed the port name for clarity. Save. Run sudo systemctl restart gunicorn to make sure the changes are reflected on the live site.

But then none of this mattered anyway, because soon after that, I ended up accidentally deleting half of my virtual environment! As a result, nothing would run. Unfortunately, simply deleting what was left of the environment and creating a new one didn’t have the intended effect; it messed up the paths. Now my Django and Gunicorn installations are out of whack, which I’m still trying to figure out the best way to fix.

As I keep coming back to dealing with this, the thing to remember is that I did it all on my own. Most people build products and apps in teams where different people are responsible for various parts of the process. Not everyone has the patience to stick through the frustration of doing a whole project by themselves. But I did, even when I was convinced I sucked, even when it felt like the odds were against me and none of this was going to lead me anywhere I wanted, professionally or personally.

And I want more of it.

(Note: seeing as you're reading this post on this site right now, I did work something out in the end. I started over on another VPS and luckily had up-to-date versions of my work on GitHub).


⟵ return to blog