June 19

Preparing Your Server for Vacation – The Unattended Server Access Checklist

Unattended Server Checklist showing steps of 1) Check VPN Connection 2) Reverse SSH Tunnel Backup 3) VNC available on backup devices 4) Test automatic server shutdown after loss of utility power 5) Test Server WOL form one of backup devices.

I am about to embark on a much-needed vacation this Friday. I travel relatively frequently for work and something that has always been a stressor in the back of my mind was leaving my homelab unattended. With my luck, as soon as I lock my door and get in the car, the server will wait for that exact minute to go down. The way I have managed this problem is by creating a checklist to ensure that, no matter where I am, I can access my network. Stuff goes wrong, that’s the nature of any real work, but I can fix anything so long as I have access. Best of all, this checklist can save you from having to call your wife and tell her to push a button on your computer!

In this post, I give you the checklist I use for unattended server access. In future posts, I will create how-to’s for implementing these features.

1) Check VPN Connection:

VPNing into my DMZ is my primary method of access for resources on my network when I am not at home. The advantages of being able to connect to my DMZ via VPN is enormous since it allows me to act just like another client on the network.

2) Check Reverse SSH Tunnel Backup (x2):

Let’s say my VPN server has gone down (in either a controlled or uncontrolled fashion); in that situation, my primary means of unattended access has gone with it- I’d be locked out of my own network. The Army has a phrase for this: “One is none, two is one, three is better.” Since we have currently only discussed one way of accessing the network remotely, applying the military’s logic, I have no way into my network to fix it; therefore, I need a backup. This is where a reverse SSH tunnel comes to the rescue. You can either create one manually or use a 3rd party service.

I use Remote.it’s connectd. With it, I can SSH into another device on my network (keeping with the idea of redundancy for critical systems, this device should not be the same one running your VPN server) and do what I need to do from there. (See WOL below).

3) VNC Server Available on Backup Devices:

My router uses a GUI, so being able to spin up a VNC server on demand from the SSH connection above is necessary.

4) Test Automatic Server Shutdown When Running on Backup Power (UPS):

I have an APC UPS directly connected to my server over USB. In the event of a power failure, the UPS tells my server that we are no longer on utility power and allows it to gracefully shutdown. Testing is essential here since it not only checks to make sure that this feature is still functional, but it also serves as a check on the UPS’s battery life.

5) Test Server Wake-on-LAN (WOL) from Backup Device:

Unlike my other network devices (router, hardware firewall, the above backup devices, etc.), my server is set up to NOT automatically restart upon the restoration of utility power. Since power outages often can have brief periods of power restoration, I don’t want it to continuously startup to then only lose power again. Therefore, after a graceful shutdown, I want the server to stay down until I bring it back up. I accomplish this via a WOL message (“magic packet”) from one of the backup devices to the server.

Category: Servers | LEAVE A COMMENT
June 11

Django Error Silver Bullets

I’ve recently been teaching myself Django. I was working on creating a new web app to handle the backend for some IoT projects I’ve been working on and recently came across two errors. In case anyone else comes across them, I will post the silver bullets below to hopefully save you some time.

1. no such table: main.auth_user__old

This was an unhandled exception that occurred whenever I tried to POST data from the Django admin:

Request Method: POST
Request URL: http://127.0.0.1:8000/admin/weatherstation/weather_recording/add/
Django Version: 2.1.1
Exception Type: OperationalError
Exception Value: no such table: main.auth_user__old
Exception Location: /home/engineer/anaconda3/envs/djangoEnv/lib/python3.5/site-packages/django/db/backends/sqlite3/base.py in execute, line 296
Python Executable: /home/engineer/anaconda3/envs/djangoEnv/bin/python
Python Version: 3.5.6
Python Path: [‘/home/engineer/Projects/WEATHERSTATION/weathersite’, ‘/home/engineer/anaconda3/envs/djangoEnv/lib/python35.zip’, ‘/home/engineer/anaconda3/envs/djangoEnv/lib/python3.5’, ‘/home/engineer/anaconda3/envs/djangoEnv/lib/python3.5/plat-linux’, ‘/home/engineer/anaconda3/envs/djangoEnv/lib/python3.5/lib-dynload’, ‘/home/engineer/anaconda3/envs/djangoEnv/lib/python3.5/site-packages’]

Solution: This problem is described in Issue #21982. It has since been fixed. Since I use Anaconda (“conda”) as my package manager, the simple fix for me was to just update my Django environment to the latest version.

2. ModuleNotFoundError: No module named ‘sqlparse’

I thought I was home free at this point now that I had updated my Django environment to the latest version in conda, but alas that was not the case. This time, I received the following error:

Traceback (most recent call last):
  File "manage.py", line 15, in <module>
    execute_from_command_line(sys.argv)
  File "/home/engineer/anaconda3/envs/djangoEnvNew/lib/python3.7/site-packages/django/core/management/__init__.py", line 381

...

File "/home/engineer/anaconda3/envs/djangoEnvNew/lib/python3.7/site-packages/django/db/backends/sqlite3/base.py", line 28,
 in <module>
    from .introspection import DatabaseIntrospection            # isort:skip
  File "/home/engineer/anaconda3/envs/djangoEnvNew/lib/python3.7/site-packages/django/db/backends/sqlite3/introspection.py",
 line 4, in <module>
    import sqlparse
ModuleNotFoundError: No module named 'sqlparse'

Thankfully the error stack is pretty helpful here. The most recent call with the error “ModuleNotFoundError: No module named ‘sqlparse'” is pretty descriptive. To resolve this error, you simply need to install the module with the following command (while in your virtual environment):

conda install sqlparse

That’s it! Hopefully this helps someone else. As always, let me know if you have any questions!

June 3

Building Blocks of Programming Languages

  • Four basic building blocks of programming languages:
  1. Expressions
  2. Statements
  3. Statement Blocks
  4. Function Blocks

1. Expressions

  • Expressions in computer programming have the same definition as expressions in math: they are a combination of an operator and its operand(s). In keeping with the mathematical definition of an expression, they are well-defined, meaning that an expression must ultimately resolve to a value.
    • An operator tells the computer to perform some kind of mathematical or logical manipulation and is performed on one or more operands
      • Examples:
        • a + b
          • + is the operator; a and b are operands
        • x – 2
          • – is the operator; a and b are the operands
        • a < b
          • < is the operator; a and b are the operands
      • With the above examples, two operands are in play, which is why you’ll hear them referred to as binary expressions
        • As a result, binary expressions use binary operators; binary operators operate on two operands
      • Operator Classification:
        • Operators can be classified based on the number of operands they perform their operation on:
          • Unary Operators
            • Take one operand
            • Example: & (address-of operator); see Pointer tutorial
          • Binary Operators
            • Operate on two operands and are by far the most common
            • Examples: +, -, <, =, etc.
          • Ternary Operators
            • Operate on three operands
        • Operators can also be classified based on the kind of function they perform:
          • Arithmetic (math) Operators:
            • i.e. Operators that perform math
            • Examples: +, -, /
          • Relational Operators:
            • Compare the values of two operands
            • Examples: >, <, ==
            • Return/resolve to a boolean: true (1) or false(0)
          • Logical Operators:
            • Combine logical expressions
            • Examples: && (AND), || (OR)
            • Return/resolve to a boolean: true; false

2. Statements:

  • Statements are syntactically complete instructions
    • In C, syntax dictates that all statements end with a semicolon (this semicolon is known as a statement terminator)
  • Example:
    • Variable assignment:
      • a = 4;
        • This is a syntactically complete instruction; note how it is simply an expression (a = 4) consisting of the assignment operator (=) with the operands a and 4, and terminating with a semicolon as required by C. By syntactically correct, we simply mean that the instruction complies with the rules of the language (i.e. syntax).

3. Statement Blocks:

  • Statement blocks group statements together so they act like a single statement (i.e. the statements act together as a block)
  • In C, statement blocks start with { and end with }. In Python, statement blocks are controlled by indentation. This is why whitespace matters in Python but not in C.
    • The code inside the statement block is known as the statement block body
  • Example:
Example of statement block

4. Function Blocks:

  • Function blocks are blocks of code that accomplish a single task
  • Functions allow you to reuse code so that if you need to do the same thing multiple times, you simply call the function tag wherever you need it; you separately define the function (with its function block) elsewhere in your code
    • This makes it easier to maintain your code since, if you need to update your function, you only have to update the code once in the function itself and not multiple times wherever the function was called
  • Functions also help when working on big projects with multiple developers by acting as a black box
    • Good functions act like a black box in the sense that you don’t have to waste your time, brainpower, or memory knowing exactly how the code inside the function (it’s function block) works; you just have to know that for a given input, you get a given output
    • This is also the basis of the idea behind libraries- you don’t have to know exactly how something is done. You just call the function (written by someone else) from the library; this forms the very basis of abstraction which allows for collaboration
  • Functions also help for code readability; instead of mentally having to parse out multiple lines of code you can look at the function name (like verifyPhoneNumber() ) and know that it verifies the phone number.
    • Example:
      • int addNum(int a, int b){//Function block here }