Dokku with Multiple Domains and Letsencrypt
Dokku is still my favourite deployment platform for my side projects. It's an easy fix for tons of different stacks, jammed onto one server (that doesn't have to deal with having the correct node or PHP version for anything).
If you aren't familiar with Dokku yet, have a look at the related articles at the bottom of this post.
Adding DomainsTo add a domain to your site there's a built in domain module which makes it trivial.
When adding domains, make sure to deploy your app before you add a domain to it. This little note is in the docs:
Adding a domain before deploying an application will result in port mappings being set. This may cause issues for applications that use non-standard ports, as those will not be automatically detected. Please refer to the proxy documentation for information as to how to reconfigure the mappings.
dokku domains:add someapp example.com dokku domains:set someapp example.com
This will add a domain to your domain pool and assing it to an app. You can see all assigned domains and their app affiliation by running
Enabling HTTPS with LetsencryptIf you don't have a some sort of setup already, you can use a community plugin called dokku-letsencrypt which will handle the creation of certs, take care of making the challenges available and provide a command for you to easily renew all your certs.
Let's have a look at the following, assuming my apps name is "someapp"
dokku config:set --no-restart someapp DOKKU_LETSENCRYPT_EMAILfirstname.lastname@example.org dokku letsencrypt someapp
The first line makes sure that Letsencrypt knows where to send emails of expiry and has a contact to reach, if you plan to sell home-cooked perscription meds over your HTTPS site ;)
In order to renew your certificates automatically, you can add a cronjob on your dokku host using
#!/bin/bash 5 5 * * * dokku letsencrypt:auto-renew >/dev/null 2>&1
This will run the auto-renew portion of the plugin and throw out the output of the tool. If you're curious you can write them to a file, but if something would be about to expire, I'd get an email anyways.
Troubleshooting: Undeployed Site ErrorIf you're running multiple domains, pointing to different apps, on your dokku host, you might run into the following error, for example when the deployment failed:
2018-03-06 16:10:59,415:ERROR:acme.challenges:324: Unable to reach http://example.com/.well-known/acme-challenge/uqjibber-y4totallynottherealthing-FCKSk_YsqgLQuyywE: HTTPSConnectionPool(host='example.com', port=443): Max retries exceeded with url: /.well-known/acme-challenge/uqDc2dLCm-y4what-FCKSk_isthis (Caused by SSLError(CertificateError("hostname 'example.com' doesn't match 'example.org'",),))
This happens when your nginx server serves up the first page it can find, instead of serving up the right domain and app.
This can be rather confusing, just be sure to check your domains point to the right thing and test the site is available in the non HTTPS version already.
Troubleshooting: Which Ports does my App use?If you want to check out which ports your apps run on, you can use
dokku proxy:report =====> captain proxy information Proxy enabled: true Proxy type: nginx Proxy port map: http:xxx:5000 =====> xxx proxy information Proxy enabled: true Proxy type: nginx Proxy port map: http:80:5000 https:443:5000 =====> trustedprovider proxy information Proxy enabled: true Proxy type: nginx Proxy port map: http:80:5000 https:443:5000
SummaryWorking with Dokku usually is a lot of fun. Sometimes it can be frustrating, but mostly it's your own fault. Writing apps that go into containers force you to be very specific about build steps. You need to know what needs to happen before the deployment can succeed. You need to add all dependencies.
For me, using one server for wildly different stacks without getting a migraine for working with different Node.js versions is reason enough for a deployment tool.