Nginx stops by itself once in a while.

Nginx stops by itself occasionally and didn’t know the reason for it. When the server got down at 3rd time, I decided to dig into the problem.

I’ve looked up syslog first.

tail -5000f /var/log/syslog

Found the following messages.

May 12 00:51:39 ip-172-31-12-44 systemd[1]: Starting Certbot...
May 12 00:51:40 ip-172-31-12-44 systemd[1]: Stopping A high performance web server and a reverse proxy server...
May 12 00:51:40 ip-172-31-12-44 systemd[1]: Stopped A high performance web server and a reverse proxy server.
May 12 00:51:46 ip-172-31-12-44 certbot[15472]: nginx: [error] open() "/run/nginx.pid" failed (2: No such file or directory)
May 12 00:51:47 ip-172-31-12-44 systemd[1]: Starting A high performance web server and a reverse proxy server...
May 12 00:51:47 ip-172-31-12-44 nginx[15559]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
May 12 00:51:47 ip-172-31-12-44 nginx[15559]: nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
May 12 00:51:47 ip-172-31-12-44 nginx[15559]: nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)
May 12 00:51:47 ip-172-31-12-44 nginx[15559]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
May 12 00:51:47 ip-172-31-12-44 nginx[15559]: nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
May 12 00:51:47 ip-172-31-12-44 nginx[15559]: nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)
May 12 00:51:48 ip-172-31-12-44 nginx[15559]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
May 12 00:51:48 ip-172-31-12-44 nginx[15559]: nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
May 12 00:51:48 ip-172-31-12-44 nginx[15559]: nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)
May 12 00:51:48 ip-172-31-12-44 nginx[15559]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
May 12 00:51:48 ip-172-31-12-44 nginx[15559]: nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
May 12 00:51:48 ip-172-31-12-44 nginx[15559]: nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)
May 12 00:51:49 ip-172-31-12-44 nginx[15559]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
May 12 00:51:49 ip-172-31-12-44 nginx[15559]: nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
May 12 00:51:49 ip-172-31-12-44 nginx[15559]: nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)
May 12 00:51:49 ip-172-31-12-44 nginx[15559]: nginx: [emerg] still could not bind()
May 12 00:51:49 ip-172-31-12-44 systemd[1]: nginx.service: Control process exited, code=exited status=1
May 12 00:51:49 ip-172-31-12-44 systemd[1]: Failed to start A high performance web server and a reverse proxy server.
May 12 00:51:49 ip-172-31-12-44 systemd[1]: nginx.service: Unit entered failed state.
May 12 00:51:49 ip-172-31-12-44 systemd[1]: nginx.service: Failed with result 'exit-code'.
May 12 00:51:49 ip-172-31-12-44 certbot[15472]: Hook command "service nginx start" returned error code 1
May 12 00:51:49 ip-172-31-12-44 certbot[15472]: Error output from service:
May 12 00:51:49 ip-172-31-12-44 certbot[15472]: Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalcte>-xe" for details.

I remember that I’ve set up a nginx server with certbot and noticed that it’s complaining about restarting nginx during certification renewal process.

Thus, I opened up the certification configuration file as below.

sudo vi /etc/letsencrypt/renewal/tinyapple.net.conf

I’ve changed the config file as below.

  1. Update authenticator from standalone to nginx.
  2. Update installer from nginx to none
  3. Comment out pre_hook.
  4. Update post_hook with service nginx restart.
# Options used in the renewal process
[renewalparams]
authenticator = nginx
installer = none
account = IDENTIFIER
#pre_hook = service nginx stop
post_hook = service nginx restart

To test the update, run the following command in order to simulate the renewal.

sudo certbot renew --dry-run

If it results without issues or errors, it’s good to go. 🙂

Advertisements

virtualenvwrapper configuration

There are files for hooks and configuration is very straight forward.
I’d like to create a new folder named src for storing all the code base. Then, change directory to the new folder. Let’s see what I can do.

There is postrmvirtualenv file under $WORKON_HOME. In my case, it is ~/venv.
Let’s open up the file in vi editor and add some hooks.

$ vi ~/venv/postrmvirtualenv

# Add following to the file and save.
path=$VIRTUAL_ENV/src
mkdir $path
cd $path

I’ve created a variable for the path of the source folder I mentioned. Then, create it and change directory to it.

Now, mkvirtualenv command lets you to create a new virtual env box and create a new folder called src under the project just created and change directory to the folder.

Let’s make some changes for workon command same as above.

I’d like to change directory to the src folder under the project once the project has been activated. Also, I’d like to change directory to the virtualenv root folder ~/venv once the project has been deactivated.

Open up postactivate and add below for activate behavior.

cd $VIRTUAL_ENV/src

Open up postactivate and add below for activate behavior.

cd $WORKON_HOME

That’s it and enjoy.

Django @property executes extra database calls? Ensure using cached result instead.

People made mistakes as below code that executes database call every time it’s invoked.

class MyModel(models.Model):
    @property
    def is_ready(self):
        status = self.check_status_from_db()
        return True if status else None

Assuming that there’re 2 or more {{ object.is_ready }} in your template especially in a loop on a list page. See what would happen via django debug toolbar.

Let’s fix the issue with the below code.

class MyModel(models.Model):
    @property
    def is_ready(self):
        if not hasattr(self, '_is_ready'):
            status = self.check_status_from_db()
            self._is_ready = True if status else None
        return self._is_ready

Now, retest the code and see what’s difference.

Django ETag doesn’t work on my local machine. Why?

Django Etag doesn’t work on my local machine via the virtual webserver.

The reason is that browser sends a request via HTTP/1.1 and django sends a response via HTTP/1.0.

How I can update the version on my machine? Here’s a monkey patch that tweak the version number.

Do not use it on your web server if you use a web webserver such as apache or nginx.

 

# HACK: without HTTP/1.1, Chrome ignores certain cache headers during development!
#       see http://stackoverflow.com/a/28033770/179583 for a bit more discussion.
from wsgiref import simple_server
simple_server.ServerHandler.http_version = "1.1"

I found this monkey patch from stackoverflow.com but unfortunately I lost the link. 😦