One place for hosting & domains

      Network

      Restricting MongoDB’s Network Exposure



      Part of the Series:
      MongoDB Security: Best Practices to Keep Your Data Safe

      MongoDB, also known as Mongo, is a document database used in many modern web applications. As with any database management system, it’s critical that those responsible for managing a Mongo database adhere to the recommended security best practices, both to prevent data from being lost in the event of a disaster and to keep it out of the hands of malicious actors.

      This series of conceptual articles provides a high-level overview of MongoDB’s built-in security features while also highlighting some general database security best practices.

      The most fundamental way you can protect the data you store in MongoDB is to limit network access to the server on which the database is running. One way to do this is to provision a virtual private network (VPN). A VPN presents its connection as if it were a local private network, allowing for secure communications between the servers within it. By running MongoDB behind a VPN, you can block access to any machine that isn’t connected to the same VPN.

      On its own, though, a VPN may not be enough to prevent unauthorized users from accessing your MongoDB installation. For instance, there may be a large number of people who need access to your VPN but only a few of them need access to your Mongo database. You could have more granular control over who has access to your data by setting up a firewall on your database server.

      A firewall provides network security by filtering incoming and outgoing traffic based on a set of user-defined rules. Firewall tools generally allow you to define rules with a high level of precision, giving you the flexibility to grant connections from specific IP addresses access to specific ports on your server. For example, you could write rules that would only allow an application server access to the port on your database server used by a MongoDB installation.

      Another way to limit your database’s network exposure is to configure IP binding. By default, MongoDB is bound only to localhost upon installation. This means that, without further configuration, a fresh Mongo installation will only be able to accept connections that originate from localhost, or the same server on which the MongoDB instance is installed.

      This default setting is secure, since it means the database is only accessible to those who already have access to the server on which it’s installed. However, this setting will cause problems if you need to access the database remotely from another machine. In such cases, you can additionally bind your instance to an IP address or hostname where the remote computer can reach the database server.



      Source link

      Introduction to PyTorch: Build a Neural Network to Recognize Handwritten Digits


      The author selected the Code 2040 to receive a donation as part of the Write for DOnations program.

      Introduction

      Machine learning is a field of computer science that finds patterns in data. As of 2021, machine learning practitioners use these patterns to detect lanes for self-driving cars; train a robot hand to solve a Rubik’s cube; or generate images of dubious artistic taste. As machine learning models grow more accurate and performant, we see increasing adoption in mainstream applications and products.

      Deep learning is a subset of machine learning that focuses on particularly complex models, termed neural networks. In later, advanced DigitalOcean articles (like this tutorial on building an Atari bot), we will formally define what “complex” means. Neural networks are the highly accurate and hype-inducing modern-day models your hear about, with applications across a wide range of tasks. In this tutorial, you will focus on one specific task called object recognition, or image classification. Given an image of a handwritten digit, your model will predict which digit is shown.

      You will build, train, and evaluate deep neural networks in PyTorch, a framework developed by Facebook AI Research for deep learning. When compared to other deep learning frameworks, like Tensorflow, PyTorch is a beginner-friendly framework with debugging features that aid in the building process. It’s also highly customizable for advanced users, with researchers and practitioners using it across companies like Facebook and Tesla. By the end of this tutorial, you will be able to:

      • Build, train, and evaluate a deep neural network in PyTorch
      • Understand the risks of applying deep learning

      While you won’t need prior experience in practical deep learning or PyTorch to follow along with this tutorial, we’ll assume some familiarity with machine learning terms and concepts such as training and testing, features and labels, optimization, and evaluation. You can learn more about these concepts in An Introduction to Machine Learning.

      Prerequisites

      To complete this tutorial, you will need a local development environment for Python 3 with at least 1GB of RAM. You can follow How to Install and Set Up a Local Programming Environment for Python 3 to configure everything you need.

      Step 1 — Creating Your Project and Installing Dependencies

      Let’s create a workspace for this project and install the dependencies you’ll need. You’ll call your workspace pytorch:

      Navigate to the pytorch directory:

      Then create a new virtual environment for the project:

      Activate your environment:

      • source pytorch/bin/activate

      Then install PyTorch. On macOS, install PyTorch with the following command:

      • python -m pip install torch==1.4.0 torchvision==0.5.0

      On Linux and Windows, use the following commands for a CPU-only build:

      • pip install torch==1.4.0+cpu torchvision==0.5.0+cpu -f https://download.pytorch.org/whl/torch_stable.html
      • pip install torchvision

      With the dependencies installed, you will now build your first neural network.

      Step 2 — Building a “Hello World” Neural Network

      In this step, you will build your first neural network and train it. You will learn about two sub-libraries in Pytorch, torch.nn for neural network operations and torch.optim for neural network optimizers. To understand what an “optimizer” is, you will also learn about an algorithm called gradient descent. Throughout this tutorial, you will use the following five steps to build and train models:

      1. Build a computation graph
      2. Set up optimizers
      3. Set up criterion
      4. Set up data
      5. Train the model

      In this first section of the tutorial, you will build a small model with a manageable dataset. Start by creating a new file step_2_helloworld.py, using nano or your favorite text editor:

      • nano step_2_helloworld.py

      You will now write a short 18-line snippet that trains a small model. Start by importing several PyTorch utilities:

      step_2_helloworld.py

      import torch
      import torch.nn as nn
      import torch.optim as optim
      

      Here, you alias PyTorch libraries to several commonly used shortcuts:

      • torch contains all PyTorch utilities. However, routine PyTorch code includes a few extra imports. We follow the same convention here, so that you can understand PyTorch tutorials and random code snippets online.
      • torch.nn contains utilities for constructing neural networks. This is often denoted nn.
      • torch.optim contains training utilities. This is often denoted optim.

      Next, define the neural network, training utilities, and the dataset:

      step_2_helloworld.py

      . . .
      net = nn.Linear(1, 1)  # 1. Build a computation graph (a line!)
      optimizer = optim.SGD(net.parameters(), lr=0.1)  # 2. Setup optimizers
      criterion = nn.MSELoss()  # 3. Setup criterion
      x, target = torch.randn((1,)), torch.tensor([0.])  # 4. Setup data
      . . .
      

      Here, you define several necessary parts of any deep learning training script:

      • net = ... defines the “neural network”. In this case, the model is a line of the form y = m * x; the parameter nn.Linear(1, 1) is the slope of your line. This model parameter nn.Linear(1, 1) will be updated during training. Note that torch.nn (aliased with nn) includes many deep learning operations, like the fully connected layers used here (nn.Linear) and convolutional layers (nn.Conv2d).
      • optimizer = ... defines the optimizer. This optimizer determines how the neural network will learn. We will discuss optimizers in more detail after writing a few more lines of code. Note that torch.optim (aliased to optim) includes many such optimizers that you can use.
      • criterion = ... defines the loss. In short, the loss defines what your model is trying to minimize. For your basic model of a line, the goal is to minimize the difference between your line’s predicted y-values and the actual y-values in the training set. Note that torch.nn (aliased with nn) includes many other loss functions you can use.
      • x, target = ... defines your “dataset”. Right now, the dataset is just one coordinate—one x value and one y value. In this case, the torch package itself offers tensor, to create a new tensor, and randn to create a tensor with random values.

      Finally, train the model by iterating over the dataset ten times. Each time, you adjust the model’s parameter:

      step_2_helloworld.py

      . . .
      # 5. Train the model
      for i in range(10):
          output = net(x)
          loss = criterion(output, target)
          print(round(loss.item(), 2))
      
          net.zero_grad()
          loss.backward()
          optimizer.step()
      

      Your general goal is to minimize the loss, by adjusting the slope of the line. To effect this, this training code implements an algorithm called gradient descent. The intuition for gradient descent is as follows: Imagine you’re looking straight down at a bowl. The bowl has many points on it, and each point corresponds to a different parameter value. The bowl itself is the loss surface: the center of the bowl—the lowest point—indicates the best model with the lowest loss. This is the optimum. The fringes of the bowl—the highest points, and the parts of the bowl closest to you—hold the worst models with the highest loss.

      To find the best model with the lowest loss:

      1. With net = nn.Linear(1, 1) you initialize a random model. This is equivalent to picking a random point on the bowl.
      2. In the for i in range(10) loop, you begin training. This is equivalent to stepping closer to the center of the bowl.
      3. The direction of each step is given by the gradient. You will skip a formal proof here, but in summary, the negative gradient points to the lowest point in the bowl.
      4. With lr=0.1 in optimizer = ..., you specify the step size. This determines how large each step can be.

      In just ten steps, you reach the center of the bowl, the best possible model with the lowest possible loss. For a visualization of gradient descent, see Distill’s “Why Momentum Really Works,” first figure at the top of the page.

      The last three lines of this code are also important:

      • net.zero_grad clears all gradients that may have been leftover from the previous step iterate.
      • loss.backward computes new gradients.
      • optimizer.step uses those gradients to take steps. Notice that you didn’t compute gradients yourself. This is because PyTorch, and other deep learning libraries like it, automatically differentiate.

      This now concludes your “hello world” neural network. Save and close your file.

      Double-check that your script matches step_2_helloworld.py. Then, run the script:

      • python step_2_helloworld.py

      Your script will output the following:

      Output

      0.33 0.19 0.11 0.07 0.04 0.02 0.01 0.01 0.0 0.0

      Notice that your loss continually decreases, showing that your model is learning. There are two other implementation details to note, when using PyTorch:

      1. PyTorch uses torch.Tensor to hold all data and parameters. Here, torch.randn generates a tensor with random values, with the provided shape. For example, a torch.randn((1, 2)) creates a 1x2 tensor, or a 2-dimensional row vector.
      2. PyTorch supports a wide variety of optimizers. This features torch.optim.SGD, otherwise known as stochastic gradient descent (SGD). Roughly speaking, this is the algorithm described in this tutorial, where you took steps toward the optimum. There are more-involved optimizers that add extra features on top of SGD. There are also many losses, with torch.nn.MSELoss being just one of them.

      This concludes your very first model on a toy dataset. In the next step, you will replace this small model with a neural network and the toy dataset with a commonly used machine learning benchmark.

      Step 3 — Training Your Neural Network on Handwritten Digits

      In the previous section, you built a small PyTorch model. However, to better understand the benefits of PyTorch, you will now build a deep neural network using torch.nn.functional, which contains more neural network operations, and torchvision.datasets, which supports many datasets you can use, out of the box. In this section, you will build a relatively complex, custom model with a premade dataset.

      You’ll use convolutions, which are pattern-finders. For images, convolutions look for 2D patterns at various levels of “meaning”: Convolutions directly applied to the image are looking for “lower-level” features such as edges. However, convolutions applied to the outputs of many other operations may be looking for “higher-level” features, such as a door. For visualizations and a more thorough walkthrough of convolutions, see part of Stanford’s deep learning course.

      You will now expand on the first PyTorch model you built, by defining a slightly more complex model. Your neural network will now contain two convolutions and one fully connected layer, to handle image inputs.

      Start by creating a new file step_3_mnist.py, using your text editor:

      You will follow the same five-step algorithm as before:

      1. Build a computation graph
      2. Set up optimizers
      3. Set up criterion
      4. Set up data
      5. Train the model

      First, define your deep neural network. Note this is a pared down version of other neural networks you may find on MNIST—this is intentional, so that you can train your neural network on your laptop:

      step_3_mnist.py

      import torch
      import torch.nn as nn
      import torch.optim as optim
      import torch.nn.functional as F
      
      from torchvision import datasets, transforms
      from torch.optim.lr_scheduler import StepLR
      
      # 1. Build a computation graph
      class Net(nn.Module):
          def __init__(self):
              super(Net, self).__init__()
              self.conv1 = nn.Conv2d(1, 32, 3, 1)
              self.conv2 = nn.Conv2d(32, 64, 3, 1)
              self.fc = nn.Linear(1024, 10)
      
          def forward(self, x):
              x = F.relu(self.conv1(x))
              x = F.relu(self.conv2(x))
              x = F.max_pool2d(x, 1)
              x = torch.flatten(x, 1)
              x = self.fc(x)
              output = F.log_softmax(x, dim=1)
              return output
      net = Net()
      . . .
      

      Here, you define a neural network class, inheriting from nn.Module. All operations in the neural network (including the neural network itself) must inherit from nn.Module. The typical paradigm, for your neural network class, is as follows:

      1. In the constructor, define any operations needed for your network. In this case, you have two convolutions and a fully connected layer. (A tip to remember: The constructor always starts with super().__init__().) PyTorch expects the parent class to be initialized before assigning modules (for example, nn.Conv2d) to instance attributes (self.conv1).
      2. In the forward method, run the initialized operations. This method determines the neural network architecture, explicitly defining how the neural network will compute its predictions.

      This neural network uses a few different operations:

      • nn.Conv2d: A convolution. Convolutions look for patterns in the image. Earlier convolutions look for “low-level” patterns like edges. Later convolutions in the network look for “high-level” patterns like legs on a dog, or ears.
      • nn.Linear: A fully connected layer. Fully connected layers relate all input features to all output dimensions.
      • F.relu, F.max_pool2d: These are types of non-linearities. (A non-linearity is any function that is not linear.) relu is the function f(x) = max(x, 0). max_pool takes the maximum value in every patch of values. In this case, you take the maximum value across the entire image.
      • log_softmax: normalizes all of the values in a vector, so that the values sum to 1.

      Second, like before, define the optimizer. This time, you will use a different optimizer and a different hyper-parameter setting. Hyper-parameters configure training, whereas training adjusts model parameters. These hyper-parameter settings are taken from the PyTorch MNIST example:

      step_3_mnist.py

      . . .
      optimizer = optim.Adadelta(net.parameters(), lr=1.)  # 2. Setup optimizer
      . . .
      

      Third, unlike before, you will now use a different loss. This loss is used for classification problems, where the output of your model is a class index. In this particular example, the model will output the digit (possibly any number from 0 to 9) contained in the input image:

      step_3_mnist.py

      . . .
      criterion = nn.NLLLoss()  # 3. Setup criterion
      . . .
      

      Fourth, set up the data. In this case, you will set up a dataset called MNIST, which features handwritten digits. Deep Learning 101 tutorials often use this dataset. Each image is a small 28x28 px image containing a handwritten digit, and the goal is to classify each handwritten digit as 0, 1, 2, … or 9:

      step_3_mnist.py

      . . .
      # 4. Setup data
      transform = transforms.Compose([
          transforms.Resize((8, 8)),
          transforms.ToTensor(),
          transforms.Normalize((0.1307,), (0.3081,))
      ])
      train_dataset = datasets.MNIST(
          'data', train=True, download=True, transform=transform)
      train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=512)
      . . .
      

      Here, you preprocess the images in transform = ... by resizing the image, converting the image to a PyTorch tensor, and normalizing the tensor to have mean 0 and variance 1.

      In the next two lines, you set train=True, as this is the training dataset and download=True so that you download the dataset if it is not already.

      batch_size=512 determines how many images the network is trained on, at once. Barring ridiculously large batch sizes (for example, tens of thousands), larger batches are preferable for roughly faster training.

      Fifth, train the model. In the following code block, you make minimal modifications. Instead of running ten times on the same sample, you will now iterate over all samples in the provided dataset once. By passing over all samples once, the following is training for one epoch:

      step_3_mnist.py

      . . .
      # 5. Train the model
      for inputs, target in train_loader:
          output = net(inputs)
          loss = criterion(output, target)
          print(round(loss.item(), 2))
      
          net.zero_grad()
          loss.backward()
          optimizer.step()
      . . .
      

      Save and close your file.

      Double-check that your script matches step_3_mnist.py. Then, run the script.

      Your script will output the following:

      Output

      2.31 2.18 2.03 1.78 1.52 1.35 1.3 1.35 1.07 1.0 ... 0.21 0.2 0.23 0.12 0.12 0.12

      Notice that the final loss is less than 10% of the initial loss value. This means that your neural network is training correctly.

      That concludes training. However, the loss of 0.12 is difficult to reason about: we don’t know if 0.12 is “good” or “bad”. To assess how well your model is performing, you next compute an accuracy for this classification model.

      Step 4 — Evaluating Your Neural Network

      Earlier, you computed loss values on the train split of your dataset. However, it is good practice to keep a separate validation split of your dataset. You use this validation split to compute the accuracy of your model. However, you can’t use it for training. Following, you set up the validation dataset and evaluate your model on it. In this step, you will use the same PyTorch utilities from before, including torchvision.datasets for the MNIST dataset.

      Start by copying your step_3_mnist.py file into step_4_eval.py. Then, open the file:

      • cp step_3_mnist.py step_4_eval.py
      • nano step_4_eval.py

      First, set up the validation dataset:

      step_4_eval.py

      . . .
      train_loader = ...
      val_dataset = datasets.MNIST(
          'data', train=False, download=True, transform=transform)
      val_loader = torch.utils.data.DataLoader(val_dataset, batch_size=512)
      . . .
      

      At the end of your file, after the training loop, add a validation loop:

      step_4_eval.py

          . . .
          optimizer.step()
      
      correct = 0.
      net.eval()
      for inputs, target in val_loader:
          output = net(inputs)
          _, pred = output.max(1)
          correct += (pred == target).sum()
      accuracy = correct / len(val_dataset) * 100.
      print(f'{accuracy:.2f}% correct')
      

      Here, the validation loop performs a few operations to compute accuracy:

      • Running net.eval() ensures that your neural network is in evaluation mode and ready for validation. Several operations are run differently in evaluation mode than when in training mode.
      • Iterating over all inputs and labels in val_loader.
      • Running the model net(inputs) to obtain probabilities for each class.
      • Finding the class with the highest probability output.max(1). output is a tensor with dimensions (n, k) for n samples and k classes. The 1 means you compute the max along the index 1 dimension.
      • Computing the number of images that were classified correctly: pred == target computes a boolean-valued vector. .sum() casts these booleans to integers and effectively computes the number of true values.
      • correct / len(val_dataset) finally computes the percent of images classified correctly.

      Save and close your file.

      Double-check that your script matches step_4_eval.py. Then, run the script:

      Your script will output the following. Note the specific loss values and final accuracy may vary:

      Output

      2.31 2.21 ... 0.14 0.2 89% correct

      You have now trained your very first deep neural network. You can make further modifications and improvements by tuning hyper-parameters for training: This includes different numbers of epochs, learning rates, and different optimizers. We include a sample script with tuned hyper-parameters; this script trains the same neural network but for 10 epochs, obtaining 97% accuracy.

      Risks of Deep Learning

      One gotcha is that deep learning does not always obtain state-of-the-art results. Deep learning works well in feature-rich, data-rich scenarios but conversely performs poorly in data-sparse, feature-sparse regimes. Whereas there is active research in deep learning’s weak areas, many other machine learning techniques are already well-suited for feature-sparse regimes, such as decision trees, linear regression, or support vector machines (SVM).

      Another gotcha is that deep learning is not well understood. There are no guarantees for accuracy, optimality, or even convergence. On the other hand, classic machine learning techniques are well-studied and are relatively interpretable. Again, there is active research to address this lack of interpretability in deep learning. You can read more in “What Explainable AI fails to explain (and how we fix that)”.

      Most importantly, lack of interpretability in deep learning leads to overlooked biases. For example, researchers from UC Berkeley were able to show a model’s gender bias in captioning (“Women also Snowboard”). Other research efforts focus on societal issues such as “Fairness” in machine learning. Given these issues are undergoing active research, it is difficult to recommend a prescribed diagnosis for biases in models. As a result, it is up to you, the practitioner, to apply deep learning responsibly.

      Conclusion

      PyTorch is deep learning framework for enthusiasts and researchers alike. To get acquainted with PyTorch, you have both trained a deep neural network and also learned several tips and tricks for customizing deep learning.

      You can also use a pre-built neural network architecture instead of building your own. Here is a link to an optional section: Use Existing Neural Network Architecture on Google Colab that you can try. For demonstration purposes, this optional step trains a much larger model with much larger images.

      Check out our other articles to dive deeper into machine learning and related fields:

      • Is your model complex enough? Too complex? Learn about the bias-variance tradeoff in Bias-Variance for Deep Reinforcement Learning: How To Build a Bot for Atari with OpenAI Gym to find out. In this article, we build AI bots for Atari Games and explore a field of research called Reinforcement Learning. Alternatively, find a visual explanation of the bias-variance trade-off in this Understanding the Bias-Variance Trade-off article.
      • How does a machine learning model process images? Learn more in Build an Emotion-Based Dog Filter. In this article, we discuss how models process and classify images, in more detail, exploring a field of research called Computer Vision.
      • Can a neural network be fooled? Learn how to in Tricking a Neural Network. In this article, we explore adversarial machine learning, a field of research that devises both attacks and defenses for neural networks for more robust real-world deep learning deployments.
      • How can we better understand how neural networks work? Read one class of approaches called “Explainable AI” in How To Visualize and Interpret Neural Networks. In this article, we explore explainable AI, and in particular visualize pixels that the neural networks believes are important for its predictions.



      Source link

      HAProxy Network Error: cannot bind socket



      Part of the Series:
      Common HAProxy Errors

      This tutorial series explains how to troubleshoot and fix some of the most common errors that you may encounter when using the HAProxy TCP and HTTP proxy server.

      Each tutorial in this series includes descriptions of common HAProxy configuration, network, filesystem, or permission errors. The series begins with an overview of the commands and log files that you can use to troubleshoot HAProxy. Subsequent tutorials examine specific errors in detail.

      Introduction

      An HAProxy cannot bind socket error message is generated when there is another process listening on the same interface and TCP port combination that HAProxy is configured to use, or when HAProxy attempts to use an IP address that is not assigned to a network interface. Both error conditions derive from the underlying operating system’s network stack.

      In the first case, when there is another process that is already using an interface and port that HAProxy is attempting to bind to, the underlying error on Linux is EADDRINUSE. The issue is that only a single process can be bound to an IP address and port combination at any given time.

      In the second case, when HAProxy is attempting to use an IP address that is not assigned to an interface on the system, the underlying error on Linux is EADDRNOTAVAIL. The issue here is that an IP socket cannot be created using an address that is not available to the operating system.

      However, both underlying errors generate the same HAProxy error message, so troubleshooting a cannot bind socket error requires examining the list of currently used sockets and IP addresses on a Linx system.

      To detect a cannot bind socket error message, you will need to examine systemctl and journalctl output to determine the IP address and port combination that are causing the error. Then you can inspect other running processes and network interfaces and decide how to resolve the issue, whether it is by switching servers, changing the IP address or port that HAProxy uses, or any combination of these options.

      Troubleshooting with systemctl

      Following the troubleshooting steps from the How to Troubleshoot Common HAProxy Errors tutorial at the beginning of this series, the first step when you are troubleshooting an cannot bind socket error message is to check HAProxy’s status with systemctl.

      The output from systemctl status will in many cases contain all the diagnostic information that you need to resolve the error. It may include the IP address that HAProxy is using, as well as the port that it is attempting to bind to. The output will also indicate how long HAProxy has been unable to start so that you can determine how long the issue has been affecting HAProxy.

      Note: If you are using Ubuntu or a Debian-derived Linux distribution, systemctl does not include output from HAProxy with a cannot bind socket error message that describes the problem. Skip to the the next section of this tutorial, Troubleshooting Using journalctl Logs to learn how to examine the systemd logs to find the conflicting IP address or port.

      On CentOS, Fedora and RedHat-derived systems, use this systemctl command to examine HAProxy’s status:

      CentOS and Fedora Systems

      • sudo systemctl status haproxy.service -l --no-pager

      The -l flag will ensure that systemctl outputs the entire contents of a line, instead of substituting in ellipses () for long lines. The --no-pager flag will output the entire log to your screen without invoking a tool like less that only shows a screen of content at a time.

      Since you are troubleshooting a cannot bind socket error message, you should receive output that is similar to the following:

      Output

      ● haproxy.service - HAProxy Load Balancer Loaded: loaded (/usr/lib/systemd/system/haproxy.service; disabled; vendor preset: disabled) Active: failed (Result: exit-code) since Wed 2020-08-19 14:57:05 UTC; 3s ago Process: 138738 ExecStart=/usr/sbin/haproxy -Ws -f $CONFIG -p $PIDFILE (code=exited, status=1/FAILURE) Process: 138736 ExecStartPre=/usr/sbin/haproxy -f $CONFIG -c -q (code=exited, status=0/SUCCESS) Main PID: 138738 (code=exited, status=1/FAILURE) Aug 19 14:57:05 92214d8ff5e2 systemd[1]: Starting HAProxy Load Balancer... Aug 19 14:57:05 92214d8ff5e2 haproxy[138738]: [ALERT] 231/145705 (138738) : Starting frontend main: cannot bind socket [0.0.0.0:80] . . . Aug 19 14:57:05 92214d8ff5e2 systemd[1]: Failed to start HAProxy Load Balancer.

      This example systemctl output includes some highlighted lines from the systemd journal that describes the error. These lines give you all the information about the error that you need to troubleshoot it further. Specifically, the line cannot bind socket [0.0.0.0:80] describes the socket that HAProxy is trying to use (0.0.0.0:80), so you can skip the following journalctl steps and instead proceed to the Troubleshooting with ss and ps Utilities section at the end of this tutorial. The other highlighted line indicates the status of the HAProxy process, which in the case of a cannot bind socket error will show Failed to start HAProxy Load Balancer.

      If your systemctl output does not give specific information about the IP address and port or ports that are causing the error (if you are using Ubuntu or Debian then this applies), then you will need to examine journalctl output from the systemd logs. The following section explains how to use journalctl to troubleshoot a cannot bind socket error.

      Troubleshooting Using journalctl Logs

      If your systemctl output does not include specifics about a cannot bind socket error, you should proceed with using the journalctl command to examine systemd logs for HAProxy.

      On Ubuntu and Debian-derived systems, run the following command:

      • sudo journalctl -u haproxy.service --since today --no-pager

      On CentOS, Fedora, and RedHat-derived systems, use this command to inspect the logs:

      • sudo journalctl -u haproxy.service --since today --no-pager

      The --since today flag will limit the output of the command to log entries beginning at 00:00:00 of the current day only. Using this option will help restrict the volume of log entries that you need to examine when checking for errors.

      If HAProxy is unable to bind to a port that is in use, search through the output for lines that are similar to the following log entries, specifically lines that contain the cannot bind socket error message as highlighted in this example:

      Output

      -- Logs begin at Wed 2020-08-19 19:38:12 UTC, end at Wed 2020-08-19 19:53:53 UTC. -- . . . Aug 19 19:39:21 92214d8ff5e2 systemd[1]: Starting HAProxy Load Balancer... Aug 19 19:39:21 92214d8ff5e2 haproxy[135]: [ALERT] 231/193921 (135) : Starting frontend main: cannot bind socket [0.0.0.0:80] Aug 19 19:39:21 92214d8ff5e2 haproxy[135]: [ALERT] 231/193921 (135) : Starting frontend main: cannot bind socket [:::80] Aug 19 19:39:21 92214d8ff5e2 systemd[1]: haproxy.service: Main process exited, code=exited, status=1/FAILURE Aug 19 19:39:21 92214d8ff5e2 systemd[1]: haproxy.service: Failed with result 'exit-code'. Aug 19 19:39:21 92214d8ff5e2 systemd[1]: Failed to start HAProxy Load Balancer. . . .

      The first highlighted line of output indicates that HAProxy cannot bind to port 80 on all available IPv4 interfaces (denoted by the 0.0.0.0 IP address). Depending on your system’s configuration, the IP addresses may be different and only show individual IPs.

      If you are using HAProxy with IPv6, then the output may also include a line like the second one that is highlighted with an IPv6 specific interface and port error, in this case :::80. The first two :: characters indicate all available IPv6 interfaces, while the trailing :80 indicates the port.

      Even though your own system may have different conflicting interfaces and ports, the errors will be similar to the output shown here. With this output from journalctl you will be able to diagnose the issue using ss, ps, and ip commands in the following section of this tutorial.

      Troubleshooting with ss and ps Utilities

      To troubleshoot a cannot bind socket error you need to determine what other process is listening on the IP address and port that HAProxy is attempting to use, or if the IP address is available to HAProxy.

      For example, if another server like Nginx is configured to listen on port 8080 on all available IPv4 network interfaces, the full socket would be 0.0.0.0:8080. If HAProxy is also configured to use 0.0.0.0:8080 then the operating system will throw an EADDRINUSE error, and HAProxy will show a cannot bind socket error message, since it cannot claim the socket for itself.

      In the previous journalctl section, something was already bound to all the available IPv4 addresses (denoted by 0.0.0.0:80). Most modern Linux distributions include a utility called ss which can be used to gather information about the state of a system’s network sockets.

      The following command will determine the name of the process that is already bound to an IPv4 interface on port 80. Ensure that you substitute the port from the error message if it is different from 80 in the following command:

      • sudo ss -4 -tlnp | grep 80

      The flags to the ss command alter its default output in the following ways:

      • -4 restricts ss to only display IPv4-related socket information.
      • -t restricts the output to tcp sockets only.
      • -l displays all listening sockets with the -4 and -t restrictions taken into account.
      • -n ensures that port numbers are displayed, as opposed to protocol names like ‘httporhttps`. This is important since HAProxy may be attempting to bind to a non-standard port and a service name can be confusing as opposed to the actual port number.
      • -p outputs information about the process that is bound to a port.
      • | grep 80 limits the output to lines that contain the characters 80 so there are fewer lines that you have to examine

      Note: in this IPv4 and the following IPv6 example, if you do not have a line in your output with a matching port, then your cannot bind socket error may be derived from an EADDRNOTAVAIL error. Skip to the next section Troubleshooting with the ip Utility to examine the available IP addresses on your system.

      With all of those flags, you should receive output like the following:

      Output

      LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=40,fd=6))

      The first three fields are not important when troubleshooting a cannot bind socket error so they can be ignored. The important fields are the fourth (0.0.0.0:80), which matches the journalctl error that you discovered earlier, along with the last users:(("nginx",pid=40,fd=6)), specifically the pid=40 portion.

      If you have a cannot bind socket error that is related to an IPv6 interface, repeat the ss invocation, this time using the -6 flag to restrict the interfaces to the IPv6 network stack like this:

      • sudo ss -6 -tlnp |grep 80

      The -6 flag limits the ip command to IPv6 interfaces. If HAProxy is unable to bind to an IPv6 socket, you should have output like the following:

      Output

      LISTEN 0 511 [::]:80 [::]:* users:(("nginx",pid=40,fd=7))

      Again, substitute the port number in question from your journalctl output if it is different from the highlighted 80 given here.

      In both these cases of IPv4 and IPv6 errors, the ss output indicates that there is a program with process ID 40 (the pid=40 in the output) that is bound to the 0.0.0.0:80 and [::]:80 interfaces respectively. This process is preventing HAProxy from starting since it already owns the port. To determine the name of the program, use the ps utility like this, substituting the process ID from your output in place of the highlighted 40 value in this example:

      You will receive output that is similar to the following:

      Output

      PID TTY TIME CMD 40 ? 00:00:00 nginx

      The highlighted nginx in the output is the name of the process that is listening on the interfaces. Now that you have the name of the program that is preventing HAProxy from starting, you can decide how to resolve the error. You could stop the nginx process, reconfigure nginx to listen on a different interface and port, or reconfigure HAProxy to avoid the port collision.

      It is important to note that the process may be different from nginx and the port and IP addresses may not always be 0.0.0.0 or [::] if you are diagnosing a cannot bind socket error. Oftentimes, different web servers and proxies will be in use on the same server. Each may be attempting to bind to different IPv4 ports and IPv6 interfaces to handle different web traffic. For example, a server that is configured with HAProxy listening on the IPv4 loopback address (also referred to as localhost) on port 8080 will show ss output like this:

      Output

      LISTEN 0 2000 127.0.0.1:8080 0.0.0.0:* users:(("haproxy",pid=545,fd=7))

      It is important to combine systemctl output, or journalctl output that indicates specific IP addresses and ports, with diagnostic data from ss, and then ps to narrow down the process that is causing HAProxy to fail to start.

      Sometimes when you are troubleshooting a cannot bind socket error message with ss and ps there will not be any output at all, which means that the error may not be caused by a socket conflict. The next section of this tutorial explains how to troubleshoot a cannot bind socket error using the ip utility.

      Troubleshooting with the ip Utility

      The previous section explained how an EADDRINUSE operating system error could cause a cannot bind socket error message. However, if you have examined ss and ps output and there is no socket conflict on your system, the issue may be caused by an EADDRNOTAVAIL operating system error instead. In this case HAProxy may be trying to bind to a socket that is not available to your operating system.

      To determine whether a cannot bind socket error is caused by an EADDRNOTAVAIL, examine both the IPv4 and IPv6 network interfaces on your system using the ip command.

      • sudo ip -4 -c address show
      • -4 restricts ip to only display IPv4-related interface information.
      • -c adds color coding to the output so that it is easier to parse visually.
      • address show displays the IP address for an interface, with the -4 and -c flags taken into account.

      You should receive output that looks similar to the following on any Linux distribution that includes the ip tool:

      Output

      1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 inet 203.0.113.1/24 brd 203.0.113.255 scope global eth0 valid_lft forever preferred_lft forever inet 192.0.2.1/24 brd 192.0.2.255 scope global eth0 valid_lft forever preferred_lft forever 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 inet 198.51.100.1/24 brd 198.51.100.255 scope global eth1 valid_lft forever preferred_lft forever

      Make a note of your IP addresses that correspond to the highlighted examples in this output. Your IP addresses and network interfaces will be different than the examples shown here. You may have more or fewer interfaces, and each may have more or fewer addresses assigned to them. The important part is to note the IP addresses from ip.

      To examine IPv6 addresses that are assigned to your system, use the ip command with the -6 flag like this:

      • sudo ip -6 -c address show

      You should receive output like the following:

      Output

      1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 state UNKNOWN qlen 1000 inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000 inet6 2604:a880:400:d1::3d3:6001/64 scope global valid_lft forever preferred_lft forever inet6 fe80::a4ff:aaff:fec9:24f8/64 scope link valid_lft forever preferred_lft forever

      Again note the highlighted values in this example output and look for the corresponding IPv6 addresses in your output.

      Once you have a list of addresses that are assigned to your system, you can try to find a matching IP address that corresponds to the cannot bind socket [x.x.x.x:80] error. If there is no IP address that matches, then HAProxy is likely configured to use an IP address that is not available to your system and the cannot bind socket error is being caused by the operating system throwing an EADDRNOTAVAIL error.

      To resolve the error you will need to edit your /etc/haproxy/haproxy.cfg file and change the bind address or addresses to an IP address that is available to your system based on the output of the ip command.

      For example, if /etc/haproxy/haproxy.cfg contained a bind line like the following using 198.51.100.123 as the IP address, but your system has 198.51.100.1 assigned based on the example output above, you will need to edit the bind line.

      Following this hypothetical example, this haproxy.cfg snippet shows the invalid IP address:

      /etc/haproxy/haproxy.cfg

      . . .
      frontend main
              bind 198.51.100.123:80
      

      A correct bind line that matches the IP address in the example ip output would look like this:

      /etc/haproxy/haproxy.cfg

      . . .
      frontend main
              bind 198.51.100.1:80
      

      Once you have edited /etc/haproxy/haproxy.cfg with the correct IP address, restart it using the systemctl command:

      • sudo systemctl restart haproxy.service

      Now examine HAProxy’s status and make sure that the output shows an active (running) line:

      • sudo systemctl status haproxy.service

      Output

      ● haproxy.service - HAProxy Load Balancer Loaded: loaded (/lib/systemd/system/haproxy.service; enabled; vendor preset: enabled) Active: active (running) since Wed 2020-08-19 21:31:46 UTC; 17h ago Docs: man:haproxy(1) file:/usr/share/doc/haproxy/configuration.txt.gz Process: 487 ExecStartPre=/usr/sbin/haproxy -f $CONFIG -c -q $EXTRAOPTS (code=exited, status=0/SUCCESS) . . . Aug 19 21:31:46 d6cdd0c71489 systemd[1]: Started HAProxy Load Balancer.

      If you have resolved the cannot bind socket error your output should be similar to this example output. The highlighted lines that show HAProxy is active, and that the process was started successfully.

      Conclusion

      In this tutorial you learned how to troubleshoot an HAProxy cannot bind socket error message on both IPv4 and IPv6 interfaces. You learned how to use systemctl to examine the status of the HAProxy server and try to find error messages. You also learned how to use journalctl to examine the systemd logs for specific information about a cannot bind socket error.

      With the appropriate error messages from the systemd logs, you then learned about the ss utility and how to use it to examine the state of a system’s network sockets. After that you learned how to combine process ID information from ss with the ps utility to find the name of the process that is causing HAProxy to be unable to start.

      Finally, in the case of a cannot bind socket error that is related to an unavailable IPv4 or IPv6 address, you learned how to use the ip utility to examine available network interfaces on your system.



      Source link