Anvil app server - MS Azure and Ubuntu 20.04

Hello folks,

I have purchased a domain name from Google and gone through the steps to set up a VM using MS Azure. I have followed Ryan’s tutorial here.

When I launch the app with:

anvil-app-server --app OpenQuestion --origin https://my_domain.org/

I get the following error:

Unable to obtain ACME certificate for domains "my_domain.org" : unable to generate a certificate for the domains ... error 400.

I have read some seemingly related posts that did not have a marked solution.

When I use nslookup www.my_domain.org my_name_server things appear to resolve correctly as follows:

I’m pretty out of my depths here but I’d like to learn more about how this all works.

Any insight would be much appreciated!

For DNS purposes I believe www and non www resolve differently, and Let’s Encrypt would treat those as unique domains. Typically you would set up your A records to resolve the domain with the www and then use a CNAME to forward www to non-www. Unless you really love www then you might want to swap that.

Just to be clear your “my_domain.org” is not the actual domain you are using correct?

Hey there,

I set up two “A” records as just as Ryan did in his tutorial (but with my own details of course). His looks like this:

I would like to know why my set up should be different from his. I’m just not familiar with so much of the terminology. Could you clarify a little bit about why Ryan’s set up would be different than mine, given my particular issue?

ps) yes, I was just using placeholders in the previous post

Some terms…

my_domain.org is a domain. That’s what you register with an isp.

www.my_domain.org is a subdomain and you can (probably) create whatever of those you want if your isp allows it.

For anyone to find that domain and subdomains, they need a dns record. Those come in many flavours. Two flavours are A records and CNAME records.

A records map a domain or subdomain to an ip address.

CNAME records act like aliases. If a subdomain needs to point at the same ip address as another subdomain, you might create one A record and then use CNAME records for the others. That way, you o ly have to change one record if the address changes.

You could use multiple A records mapping to the same address and it will work fine. It’s just more effort if the address changes.

Many domains set an A record at the domain level pointing to a Web server and create a www subdomain with a CNAME record. That way, users typing either in their browser end up at the same website.

SSL certificates are choosy about what domains and subdomains they are valid for and they treat the two as separate beings.

It’s possible that a certificate will handle both levels but you ha e to explicitly define that when you create the certificate. By default, they often only handle one.

So, your certificate needs to match precisely the subdomains you type into your browser. Even if you correctly use A and CNAME records to map multiple domains and subdomains to the correct address, your certificate might only be valid for one of those.

3 Likes

Thanks so much for the helpful information. I’m slowly getting my head around it.

In Ryan’s example, he created two A records. I did the same as that does not appear to be wrong (albeit less efficient perhaps).

He called the app with:

anvil-app-server --app OpenQuestion --origin https://my_domain.org/

Then the docs say:

Thanks to Anvil’s built-in integration with Let’s Encrypt, we can specify an https:// origin, and Anvil will take care of the rest.

But it sounds like I actually do need to do some extra steps here to configure things properly.

Do you know what specifically I might need to do? I will keep Googling of course.

That sounds like your certificate should handle the multiple levels.

The error looks like it’s actually failing to generate the certificate in the first place.

Possibly either lets encrypt has a problem or the existence of your domain hasn’t yet replicated to their dns servers.

You could try going to their website and creating one manually.

1 Like

Ah, okay. Great. Let me investigate that!

I’ve been following the instructions on letsencrypt.

They recommend using the Certbot ACME client.

I followed the Certbot instructions on their site. When Certbot tries to issue me a certificate with:

sudo certbot certonly --standalone

I get the following error:

(env) me@azure_vm:~$ sudo certbot certonly --standalone
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator standalone, Installer None
Please enter in your domain name(s) (comma and/or space separated)  (Enter 'c'
to cancel): my_domain.org
Requesting a certificate for my_domain.org
Performing the following challenges:
http-01 challenge for my_domain.org
Waiting for verification...
Challenge failed for domain my_domain.org
http-01 challenge for my_domain.org
Cleaning up challenges
Some challenges have failed.

IMPORTANT NOTES:
 - The following errors were reported by the server:

   Domain: my_domain.org
   Type:   connection
   Detail: Fetching
   http://my_domain.org/.well-known/acme-challenge/...:
   Timeout during connect (likely firewall problem)

   To fix these errors, please make sure that your domain name was
   entered correctly and the DNS A/AAAA record(s) for that domain
   contain(s) the right IP address. Additionally, please check that
   your computer has a publicly routable IP address and that no
   firewalls are preventing the server from communicating with the
   client. If you're using the webroot plugin, you should also verify
   that you are serving files from the webroot path you provided.

I just purchased the domain name yesterday afternoon so perhaps I just need time. I am certainly trying to figure this out but if anything else comes to mind please let me know if you have a second.

If there is no app (or website or really anything that loads and returns HTTP 200) currently available at that domain then Let’s Encrypt won’t issue the certificate.

If you want to “hack” the certificate you could spin up a quick Apache server and use the standard html file it generates to get the certificate. But then you would need to remove Apache and ensure it isn’t stuck on port 80 or 443.

Have you been able to launch the app without SSL? Just to see if the domain is actually working

Here is a yml file of an app that is working currently.

origin: "https://my_domain.mn:443"
origin: "https://www.my_domain.mn:443"
http-redirect-port: 80

Note: I added the second origin just because it seemed like I should. I have no idea if this is doing anything and it’s there because I thought it would help Let’s Encrypt issue another certificate for the sub domain, which it didn’t seem to. I tried using two A records like in Ryans tutorial, but then SSL wasn’t working on www.

My DNS records are:

  • A record for root (@) to the server IP
  • CNAME from www to root

This isn’t the only way to do this, but it worked for me.

I use Amazon LightSail with above code, work after edit firewall

So this is probably a stupid question but when I go to the domain (type it in the address bar) that I purchased, I just get a timeout since there’s nothing there. Based on your comment, that is not what I should expect right?

Do you have the Anvil app running without SSL currently on the IP that the domain is pointing to?

I do believe that a website or something needs to load for Let’s Encrypt to issue a certificate. I’m guessing the way this works for Anvil’s integration is that the app server is launched, then the Let’s Encrypt bot checks the challenges. After everything passes the certificate is updated and the setup tool updates the built-in web server config.

I’m making educated guesses mostly based on my experience with web servers and also with setting up an Anvil app.

Have you been able to get the app server to work on that domain even without SSL?

Hey there.

I don’t think I’ve tried to get it working without SSL as far as I understand.

I will have to resarch how to do that.

I did however try starting a new VM. Last time I chose Ubuntu 18 accidently. This time I chose Ubuntu 20 (just as Ryan did). I followed the same steps (but added a CNAME as suggested) and now when I run:

anvil-app-server --app my_app --origin https://my_domain.org/ --letsencrypt-staging

Nothing happens lol. I just see the print out:

Found Anvil App Server JAR in package directory

The command line comes back to my control and no web server starts up (I think that is the right terminology).

I think this might be progress but I’m not sure :slight_smile:

EDIT: I can also see that despite my network security rule, the machine is not listening on port 443 when I check with sudo lsof -i -P -n | grep LISTEN .

The mention in the tutorial about the ports is certainly confusing for those not steeped in the wizardry of sysadmin. By default non-root processes are not allowed to bind to certain ports. However if the port isn’t available to bind to the Anvil app server should give an error to that effect.

For me the command in the tutorial didn’t work (but I think it was a root issue on my machine). This is what I used:

/sbin/sysctl -w net.ipv4.ip_unprivileged_port_start=0

This sets the start point for unprivileged ports on the machine to 0. This basically makes all low numbered ports as unprivileged, hence able to have a non-root service bound to them. Technically this is more permissive than it should be, but realistically this isn’t a big risk unless someone/something can get an account on the machine.

Side note: Here is my horror story, when trying to get my app launched and properly configured it took me about 12 hours from start to finish. I probably tried hundreds of permutations. It’s still a new open source package and there are definitely some rough edges for sure.

1 Like

I really appreciate this. I’m still trying and learning a lot along the way. I’ve deleted and remade the VM and followed the tutorial a few times now. I feel closer despite it not working quite yet.

I’m looking forward to trying the command you just shared!

@robert Hmm, unfortunatley no luck with:
/sbin/sysctl -w net.ipv4.ip_unprivileged_port_start=0

For some reason I cannot get port 443 to be open on the Ubuntu box. My firewall is allowing 443 though, but still no luck and no errors.

Success!! :dart: :sweat_smile:

Thank you to you all for teaching me…the internet. It’s all a good reminder as to why I pay for Anvil.

In addition to Ryan’s tutorial, I did the following two things:

  1. adjusted my VM’s firewall settings so that port 443 was open.
sudo ufw allow ssh
sudo ufw enable
sudo ufw allow 443
  1. As recommended by letsencrypt, I got myself a certificate from certbot by following their instructions:
sudo snap install core
sudo snap refresh core
sudo apt-get remove certbot
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo certbot certonly --standalone

After running the certbot commands, I got the following reassuring print out:

Congratulations! Your certificate and chain have been saved at:

Your key file has been saved at:

Your certificate will expire on … To obtain a new or
tweaked version of this certificate in the future, simply run
certbot again. To non-interactively renew all of your
certificates, run “certbot renew”

I believe that those were the two factors that were interacting to thwart my efforts.

Thank you to @owen.campbell, @Tony.Nguyen, and @robert for all of your helpful pointers.

3 Likes

Glad you got it working. I actually had a weird firewall config on my server. UFW is much more standard on most machines.

1 Like