Nginx not taking into account renewed let's encrypt certificates - ssl

I have a server running some NodeJs apps (MeteorJs to be precise) on internal ports. I use Nginx to proxy_pass requests that are targeting URLs to the apps.
Let's say app_1 is running on localhost:3000, I would proxy_pass app1.domain.com to localhost:3000 and then add firewall rule to restrict access on port 3000.
Then I add SSL on the incoming connection for app1.domain.com using letsencrypt. I generate certs using certbot certonly -w /var/www/app1 -d app1.domain.com and then set the nginx config file to use it.
Everything works flawlessly until it's time to renew the cert.
To do the renewal, I have the following cron job :
12 6 * * 3 /root/renew.sh
with the following script /root/renew.sh :
certbot renew
service nginx reload
The problem I have is that upon expiration, the nginx webserver is not serving the new certificate !
So I added the following cron job :
30 6 * * 3 service nginx restart
but it still fails to refresh the certificate (which leads to error in navigators, saying connexion is not secure because of cert expiration). So I need to manually log in and reload nginx.
What is wrong in my setup ?
Thanks

You can set everything in one cronjob line (modified basic setup):
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew --deploy-hook "nginx -t && systemctl restart nginx"
This cron job is triggered twice every day to check if certificate is getting expired in next 30 days or not. It shouldn't cause performance problems.
If it is getting expired then it will auto renew it quietly without generating output and restart NGINX to apply changes. If certificate is not getting expired then it will not perform any action.
Be aware --deploy-hook argument was added in certbot version 0.17, released in July 2017

After more testing, here is the answer to this issue:
Set the cron job to point to a bash script:
12 6 * * 3 /root/renew.sh
And set the bash script like this:
certbot renew
sleep 1m
service nginx reload
Note the presence of the sleep command which allows to wait until the renewal is done

Related

recommandation automate ssl renewal letsencrypt

I use this article to do config and everything ok .
I want now to automate renew of my ssl certificate with crontab
yes i use debian
This is the command to renew
$ docker compose run --rm certbot renew
This is what i choose in my crontab
0 0 * * *
The question is whether this configuration is good or if you know a slightly healthier practice, I'm interested.
Thanks in advance

Certbot unable to find AWS credentials when issuing certificate via dns for route53

I need to get an certificate for my domain hosted on AWS Route 53 from LetsEncrypt. I do not have any port 80 or 443 exposed since the server is used for VPN and does not have a public access.
So the only way to do this is via DNS validation of route 53.
So far I have installed certbot and dns-route53 plugin
sudo snap install --beta --classic certbot
sudo snap set certbot trust-plugin-with-root=ok
sudo snap install --beta certbot-dns-route53
sudo snap connect certbot:plugin certbot-dns-route53
I have created a special user in my AWS account who has access to Route53 and I have added the access key id and secret access key in the ~/.aws/config and also ~/.aws/credentials which looks something like this
[default]
aws_access_key_id=foo
aws_secret_access_key=bar
Basically followed every step given here: https://certbot-dns-route53.readthedocs.io/en/stable/
Now when I run the following command:
sudo certbot certonly -d mydomain.com --dns-route53
It gives the following output:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator dns-route53, Installer None
Requesting a certificate for mydomain.com
Performing the following challenges:
dns-01 challenge for mydomain.com
Cleaning up challenges
Unable to locate credentials
To use certbot-dns-route53, configure credentials as described at https://boto3.readthedocs.io/en/latest/guide/configuration.html#best-practices-for-configuring-credentials and add the necessary permissions for Route53 access.
I went to the documentation given in the error message: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html#best-practices-for-configuring-credentials
but I do not think there is anything wrong I am doing
I even went to the root level by doing sudo su and exported the AWS keys as env vars there and even exported the AWS keys in the home as well but it still throws me the same error.
so I also ran into this same issue, and it's likely because of you running certbot with sudo, when do you do that, whatever user you've used as ~/, is ignored, as instead, it's looking in /root/.
I fixed it by (centos) is my user where I have the .aws/ directory with config and credential files.
sudo -s
ln -s /home/centos/.aws/ ~/.aws
ls -lsa ~/.aws
... /root/.aws -> /home/centos/.aws/

How can I deploy a secure (HTTPS) Meteor app on Heroku?

I would like to deploy my Meteor app to Heroku and make it only accessible through HTTPS. Ideally, I want to do this as cheaply as possible.
Create the Certificate
Run these commands to get certbot-auto. certbot-auto should work on most systems
wget https://dl.eff.org/certbot-auto
chmod 755 certbot-auto
This command starts the process of getting your certificate. The -d flag allows you to pass in the domain you would like to secure. Alternatively, without the -d flag, it will pop up a prompt where you can enter the domain.
./certbot-auto certonly --manual -d app.yoursite.com
Then it will ask you the following. Do not hit enter.
Make sure your web server displays the following content at
http://app.yoursite.com/.well-known/acme-challenge/SOME-LENGTHY-KEY before continuing:
SOME-LONGER-KEY
Use Picker
I suggest using this method because on renewal, you will only need to update an environment variable. You can use public/ as below, but it will require a rebuild of your entire app every time
Run meteor add meteorhacks:picker
In a server side file, add the following
import { Picker } from 'meteor/meteorhacks:picker';
Picker.route('/.well-known/acme-challenge/:routeKey', (params, request, response) => {
response.writeHead('200', {'Content-Type': 'text/plain'});
response.write(process.env.SSL_PAGE_KEY)
response.end();
});
Then set an environment variable SSL_PAGE_KEY to SOME-LONGER-KEY with
heroku config:set SSL_PAGE_KEY=SOME-LONGER-KEY
Use public/
Create the directory path in your public folder. If you don't have one, create one.
mkdir -p public/.well-known/acme-challenge/
Then create the file SOME-LENGTHY-KEY and place SOME-LONGER-KEY inside it
echo SOME-LONGER-KEY > public/.well-known/acme-challenge/SOME-LENGTHY-KEY
Commit and push that change to your Heroku app.
git push heroku master
Now hit enter to continue the verification process. You should receive a message like this
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/app.yoursite.com/fullchain.pem. Your cert will
expire on 2016-04-11. To obtain a new version of the certificate in
the future, simply run Let's Encrypt again.
Upload the Certificate
To upload your certificates to Heroku, first enable the SSL Beta
heroku labs:enable http-sni -a your-app
heroku plugins:install heroku-certs
Then add your fullchain.pem and privkey.pem to Heroku.
sudo heroku _certs:add /etc/letsencrypt/live/app.yoursite.com/fullchain.pem /etc/letsencrypt/live/app.yoursite.com/privkey.pem
You can verify that the certificate was uploaded with
heroku _certs:info
Change your DNS Settings
Update your DNS to point to app.yoursite.com.herokudns.com
Verify SSL is working
To check that SSL is set up, run the following. -v gives you verbose output. -I shows the document info only. -H passes a header to the URL. The header we're passing ensures that a cache is not being used and will ensure you get your new certificate and not an old one.
curl -vI https://app.yoursite.com -H "Cache-Control: no-cache"
Check that the output contains the following
* Server certificate:
* subject: C=US; ST=CA; L=SF; O=SFDC; OU=Heroku; CN=app.yoursite.com
If the subject line does not contain CN=app.yoursite.com, wait 5 to 10 minutes and try again. If it does, you're almost good to go.
Make Meteor Specific Changes
To finish up the process, you'll want to change your ROOT_URL environment variable to the new https version.
heroku config:set ROOT_URL=https://app.yoursite.com
Then you'll want to ensure that your users are always using SSL with the force-ssl package
meteor add force-ssl
Lastly, if you have any OAuth logins set up in your app (Facebook, Google, etc), you'll want to provide them with the new https version of your URL.
Renewal
Run certbot-auto again
./certbot-auto certonly --manual -d app.yoursite.com
It may prompt you for the same endpoint with the same content. If it does, just hit enter. If it does not, you will need to repeat the above steps.
It will then create new certificate files, which you will upload to Heroku with
heroku certs:update /etc/letsencrypt/live/app.yoursite.com/fullchain.pem /etc/letsencrypt/live/app.yoursite.com/privkey.pem
Then to confirm, run the Verify SSL is working commands above
Sources
https://certbot.eff.org/#ubuntutrusty-other
https://devcenter.heroku.com/articles/ssl-beta
https://themeteorchef.com/blog/securing-meteor-applications/

How to solve a challenge to authorize my domain for letsencrypt?

I'm trying to authorize my domain for letsencrypt. Previously, a few months ago on a different server, I didn't it, now I do for some reason.
./letsencrypt-auto certonly -a webroot --webroot-path=/home/deployer/pfios -d my_website.com -d www.my_website.com
Failed authorization procedure. my_website.com (http-01): urn:acme:error:unauthorized :: The client lacks sufficient authorization :: The key authorization file from the server did not match this challenge [fdsfs-fdsfdsf.fdsfdsfds333] != [gangnam style!]
Domain: www.my_website.com
Type: unauthorized
Detail: The key authorization file from the server did not match
this challenge
[fdsfs-fdsfdsf.fdsfdsfds333]
!= [gangnam style!]
The code for authorization or rather the name of a file is different each time. Where should I actually retrieve it? In this case it's "fdsfs-fdsfdsf.fdsfdsfds"
Try authorize your domain via standalone webserver from LE.
./letsencrypt-auto certonly -a standalone -d my_website.com -d www.my_website.com
You must remember - when you generate new cert you must off your main webserver (Apache, nginx, etc.)
In my case solved it by running
sudo apt-get update and then running the renew command
/usr/bin/letsencrypt renew
Check if you have IPV6 redirection configured in your DNS provider.
If the redirection does not redirect to your server, remove it.

Puppet: could not retrieve catalog from remote server

Running sudo puppet agent -t from host: host.internaltest.com
err: Could not retrieve catalog from remote server: Error 400 on SERVER: Another local or imported resource exists with the type and title Host[host.internaltest.com] on node host.internaltest.com
This machine had its ssl certs messed with so I cleaned it off the master and then using autosign (bad bad i know!) I ran sudo puppet agent -t which regenerated the ssl cert but also threw this error. Let me know if you need more information, I haven't delete with this aspect of puppet too much.
Most likely puppetmaster has this cert in the memory. You need to clean the cert both on client and in the master
#On client machine do this assuming puppet libdir = /var/lib/puppet
rm -rf /var/lib/puppet/ssl/*/*.pem
#On the puppet-master
puppet cert clean host.internaltest.com
# Restart puppet-master
/sbin/service puppetmasterd restart
# If you are using puppet-master behind passenger, you may need to restart httpd
/sbin/service httpd restart
# then run puppet agent on the client to regenerate the cert
If one uses an stunnel and globally set http_proxy this error will occur when it is redirected to the wrong endpoint.