<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: vinsu rick </title>
    <description>The latest articles on DEV Community by vinsu rick  (@vinsu).</description>
    <link>https://dev.to/vinsu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F367949%2F3173f5c0-5af8-4674-b119-47bb1db0212d.png</url>
      <title>DEV Community: vinsu rick </title>
      <link>https://dev.to/vinsu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vinsu"/>
    <language>en</language>
    <item>
      <title>Automating Linux User Management and Permissions with Bash Scripting</title>
      <dc:creator>vinsu rick </dc:creator>
      <pubDate>Fri, 05 Jul 2024 19:19:43 +0000</pubDate>
      <link>https://dev.to/vinsu/automating-linux-user-management-and-permissions-with-bash-scripting-24k9</link>
      <guid>https://dev.to/vinsu/automating-linux-user-management-and-permissions-with-bash-scripting-24k9</guid>
      <description>&lt;p&gt;In this article, I'll be walking through the steps to create a user management bash script to meet some predefined requirements. The main goal of the script is to allow an administrator to create users and groups for different purposes within a linux environment, so without plenty talk lets get into it &lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Users and their groups are defined in a text file that will be supplied to the script as an argument&lt;/li&gt;
&lt;li&gt;A corresponding home directory will be created for each user&lt;/li&gt;
&lt;li&gt;User passwords should be stored securely in a file with path /car/secure/user_passwords.txt&lt;/li&gt;
&lt;li&gt;Logs of all actions should be logged to /var/log/user_management.log&lt;/li&gt;
&lt;li&gt;Only the owner, in this case root, should be able to access the user_password.txt file&lt;/li&gt;
&lt;li&gt;Errors should be gracefully handled&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Creating users
&lt;/h2&gt;

&lt;p&gt;To create a user, you can use the useradd command. This command can be set to create a user, create their home directory, and set their password. If you simply wish to add a user to the linux system, you can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo useradd &amp;lt;username&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;&amp;lt;username&amp;gt;&lt;/code&gt; here is the name of the user you wish to add. However, if you wish to create a home directory and add a password, you can run this instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo useradd -m -p $(openssl passwd -6 "$password") &amp;lt;username&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command uses the &lt;code&gt;-m&lt;/code&gt; flag to add a home directory and the &lt;code&gt;-p&lt;/code&gt; flag to add a password (encrypted using openssl) for the user.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding users to groups
&lt;/h2&gt;

&lt;p&gt;By default, when a user is created, a personal group with their username is also created. This means you won't need to explicitly create this. However, to add a user to group, say sudo, you must use the usermod command. Find the basic command structure below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo usermod -aG "&amp;lt;group&amp;gt;" "&amp;lt;user&amp;gt;"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The -a flag is used to append the user to the new group without removing them from existing groups. The -G flag on the other hand specifies the group that the user will be added to, in this case, .&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating groups
&lt;/h2&gt;

&lt;p&gt;When a group doesn't exist, it should be created before a user is added to it. Groups are typically created using the groupadd command. Here's an example of the command in action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo groupadd "&amp;lt;group&amp;gt;"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Combining user creation, group creation, and group addition
&lt;/h2&gt;

&lt;p&gt;You can command user creation, group creation, and adding a user to a group in a script. Say you have your users and groups defined in a semi-colon delimited script like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;user1; group1, group2
user2; group3,group6
user3;group2,group3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can write a script that loops through the file, extracts the relevant information, and creates the users and groups.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;USERS_FILE=$1

mapfile -t lines &amp;lt; "$USERS_FILE"

# loop over each line in the array
for line in "${lines[@]}"; do
    # Remove leading and trailing whitespaces
    line=$(echo "$line" | xargs)

    # Split line by ';' and store the second part
    IFS=';' read -r user groups &amp;lt;&amp;lt;&amp;lt; "$line"

    # Remove leading and trailing whitespaces from the second part
    groups=$(echo "$groups" | xargs)

    # Create a variable groupsArray that is an array from spliting the groups of each user
    IFS=',' read -ra groupsArray &amp;lt;&amp;lt;&amp;lt; "$groups"

    # Generate a 6-character password using pwgen
    password=$(pwgen -sBv1 6 1)

    # Create the user with the generated password
    sudo useradd -m -p $(openssl passwd -6 "$password") "$user"

    # loop over each group in the groups array
    for group in "${groupsArray[@]}"; do
        group=$(echo "$group" | xargs)

        # Check if group exists, if not, create it
        if ! grep -q "^$group:" /etc/group; then
            sudo groupadd "$group"
            echo "Created group $group"
        fi

        # Add user to the group
        sudo usermod -aG "$group" "$user"
        echo "Added $user to $group"
    done

    echo "User $user created and added to appropriate groups"
done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, the script above does the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It takes in a single argument, expressed using $1. It then sets this argument as the variable, $USERS_FILE.&lt;/li&gt;
&lt;li&gt;It uses the mapfile command to load the content of the $USERS_FILE into an array called lines.&lt;/li&gt;
&lt;li&gt;It loops through each lines of lines and extracts the user and groups using the Internal Field Separator (IFS) shell command.&lt;/li&gt;
&lt;li&gt;It generates a 6-character password using pwgen. pwgen is linux package that allows you to create passwords to your exact specification.&lt;/li&gt;
&lt;li&gt;It loops over the groups, after splitting each group into groups using IFS, creates the group if it doesn't exist, and adds the user to the group.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Securing the script: Hashing passwords with openssl
&lt;/h2&gt;

&lt;p&gt;While the script above performs all the operations needed to create users and groups, and then add the users to groups, it does not consider security. The major security issue is that the generated passwords are added to users in plaintext format. To solve this problem, you can utilize openssl to hash the password. You can simply run openssl passwd -6 (generated_password) to achieve hashing. This command uses the SHA 512 algorithm for hashing. It's security is comparable to SHA 256 which is the most prominent hashing algorithm on the internet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Encrypting and storing the passwords
&lt;/h2&gt;

&lt;p&gt;Since this script creates users, it is wise to capture the generated passwords in a file. But to do that securely, the passwords must be encrypted. Password encryption can also be done using openssl. But it'll require and encryption key. You can use the command below to generate, encrypt, and store a password.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Generate a 6-character password using pwgen
    password=$(pwgen -sBv1 6 1)

    # Encrypt the password before storing it
    encrypted_password=$(encrypt_password "$password" "$PASSWORD_ENCRYPTION_KEY")

    # Store the encrypted password in the file
    echo "$user:$encrypted_password" &amp;gt;&amp;gt; "$PASSWORD_FILE"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;$PASSWORD_ENCRYPTION_KEY&lt;/code&gt; and &lt;code&gt;$PASSWORD_FILE&lt;/code&gt; must be defined for this operation to complete successfully.&lt;/p&gt;

&lt;p&gt;A look at the secure script&lt;br&gt;
Here's the updated script with the password encryption and password hashing functionalities:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

PASSWORD_FILE_DIRECTORY="/var/secure"
PASSWORD_FILE="/var/secure/user_passwords.txt"
PASSWORD_ENCRYPTION_KEY="secure-all-things"
USERS_FILE=$1

# Function to encrypt password
encrypt_password() {
    echo "$1" | openssl enc -aes-256-cbc -pbkdf2 -base64 -pass pass:"$2"
}

# Create the directory where the user's password file will be stored
sudo mkdir -p "$PASSWORD_FILE_DIRECTORY"
sudo touch "$PASSWORD_FILE"
sudo chmod 600 "$PASSWORD_FILE" # Set read permission for only the owner of the file
sudo chown root:root "$PASSWORD_FILE" # Set the owner as the root user

# load the content of the users.txt file into an array: lines
mapfile -t lines &amp;lt; "$USERS_FILE"

# loop over each line in the array
for line in "${lines[@]}"; do
    # Remove leading and trailing whitespaces
    line=$(echo "$line" | xargs)

    # Split line by ';' and store the second part
    IFS=';' read -r user groups &amp;lt;&amp;lt;&amp;lt; "$line"

    # Remove leading and trailing whitespaces from the second part
    groups=$(echo "$groups" | xargs)

    # Create a variable groupsArray that is an array from spliting the groups of each user
    IFS=',' read -ra groupsArray &amp;lt;&amp;lt;&amp;lt; "$groups"


    # Generate a 6-character password using pwgen
    password=$(pwgen -sBv1 6 1)

    # Encrypt the password before storing it
    encrypted_password=$(encrypt_password "$password" "$PASSWORD_ENCRYPTION_KEY")

    # Store the encrypted password in the file
    echo "$user:$encrypted_password" &amp;gt;&amp;gt; "$PASSWORD_FILE"

    # Create the user with the generated password
    sudo useradd -m -p $(openssl passwd -6 "$password") "$user"

    # loop over each group in the groups array
    for group in "${groupsArray[@]}"; do
        group=$(echo "$group" | xargs)

        # Check if group exists, if not, create it
        if ! grep -q "^$group:" /etc/group; then
            sudo groupadd "$group"
            echo "Created group $group"
        fi

        # Add user to the group
        sudo usermod -aG "$group" "$user"
        echo "Added $user to $group"
    done

    echo "User $user created and password stored securely"
done

# remove the created password from the current shell session
unset password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script above includes the additional functionality as preventing non-root users from accessing the password storage file and also removing the password variable using unset password from the shell where it is run.&lt;/p&gt;

&lt;p&gt;Adding logging to the script&lt;br&gt;
The script can be further improved by logging the commands to a log file. This file can be defined as a variable at the top of the script then a redirection command can be added to redirect logs from the script to the log file. We can also direct errors that might occur to the std out, that's the normal output you see when you run commands without errors. Both log types will ultimately be sent to the log file. The command below illustrates this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Redirect stdout and stderr to log file
exec &amp;gt; &amp;gt;(tee -a "$LOG_FILE") 2&amp;gt;&amp;amp;1 
echo "Executing script... (note that this line will be logged twice)" | tee -a $LOG_FILE 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The echo "Executing script..." command is added so that the normal console shows the logs too. It's not wise to run a script without seeing an output. The addition of this line will ultimately mean it gets shown in the log file twice, but this is the compromise that has to be made.&lt;/p&gt;

&lt;p&gt;Adding Error Handling&lt;br&gt;
Errors can be handled and prevented using exception handling. We can add functions that check that both openssl and pwgen are installed, otherwise installs them. When can also add handlers that check if arguments are not passed to the script and if the argument passed for the user's file is a valid file. Here's a snippet with these exception handlers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

LOG_FILE="/var/log/user_management.log"
PASSWORD_FILE_DIRECTORY="/var/secure"
PASSWORD_FILE="/var/secure/user_passwords.txt"
PASSWORD_ENCRYPTION_KEY="secure-all-things"
USERS_FILE=$1

# Function to display usage information
usage() {
    echo "Usage: $0 &amp;lt;user-data-file-path&amp;gt;"
    echo "    &amp;lt;user-data-file-path&amp;gt;: Path to the file containing user data."
    echo
    echo "The user data file should contain lines in the following format:"
    echo "    username;group1,group2,..."
    echo
    echo "Example:"
    echo "    light; dev,sudo"
    echo "    mayowa; www-data, admin"
    exit 1
}

# Check if script is run with sudo
if [ "$(id -u)" != "0" ]; then
    echo "This script must be run with sudo. Exiting..."
    exit 1
fi


# Check if an argument was provided
if [ $# -eq 0 ]; then
    echo "Error: No file path provided."
    usage
fi

# Check if the user's data file exists
if [ ! -e "$USERS_FILE" ]; then
    echo "Error: The provided user's data file does not exist: $USERS_FILE"
    usage
fi

# Function to check if a package is installed
is_package_installed() {
    dpkg -s "$1" &amp;gt;/dev/null 2&amp;gt;&amp;amp;1
}

# Check if openssl is installed
if ! is_package_installed openssl; then
    echo "openssl is not installed. Installing..."
    sudo apt-get update
    sudo apt-get install -y openssl
fi

# Check if pwgen is installed
if ! is_package_installed pwgen; then
    echo "pwgen is not installed. Installing..."
    sudo apt-get update
    sudo apt-get install -y pwgen
fi

# Check if the file exists
if [ ! -f "$USERS_FILE" ]; then
    echo "Error: $USERS_FILE not found."
    exit 1
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An exception is also added that checks if the script was run using the sudo command. This is because sudo is required to perform useradd and groupadd operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;You can find the complete script in this &lt;a href="https://github.com/vinuch/bash-user-management" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;. A big thanks to &lt;a href="https://hng.tech" rel="noopener noreferrer"&gt;HNG&lt;/a&gt; for providing this chance to dive into advanced bash scripting through a practical example. To join an upcoming HNG internship, keep an eye on &lt;a href="https://hng.tech/internship" rel="noopener noreferrer"&gt;their internship page&lt;/a&gt;. You can also hire top talent for your project through the HNG network by visiting &lt;a href="https://hng.tech/hire" rel="noopener noreferrer"&gt;HNG Hire&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Behind the Scenes: How I Tackled Connecting to Multiple Databases in Golang</title>
      <dc:creator>vinsu rick </dc:creator>
      <pubDate>Tue, 02 Jul 2024 11:13:57 +0000</pubDate>
      <link>https://dev.to/vinsu/behind-the-scenes-how-i-tackled-connecting-to-multiple-databases-in-golang-40dl</link>
      <guid>https://dev.to/vinsu/behind-the-scenes-how-i-tackled-connecting-to-multiple-databases-in-golang-40dl</guid>
      <description>&lt;h2&gt;
  
  
  The challenge
&lt;/h2&gt;

&lt;p&gt;Connecting your backend application to a database is a necessary step to take if you intend on persisting data within your application to be retrieved later in the future.&lt;br&gt;
There are different types of databases each with different tradeoffs or pros and cons more like the different types of dbs have usecases where they shine better and others where another option might be better or more efficient. Ultimately it is up to you the developer to choose what database to use in your particular usecase.&lt;/p&gt;

&lt;p&gt;Two of the more popular types of databases are:&lt;/p&gt;
&lt;h2&gt;
  
  
  Relational Databases (RDMS)
&lt;/h2&gt;

&lt;p&gt;Often referred to as relational database management systems (RDMS). they store data in tables with predefined schemas, and they use SQL (structured query language) for defining and manipulating the data&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples: MySQL, PostgreSQL, Oracle Database, Microsoft SQL Server etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  NoSQL databases
&lt;/h2&gt;

&lt;p&gt;NoSQL databases as the name suggests are databases that don't require SQL for defining and manipulating data. They are designed for flexibility, scalability, and performance. They do not require a fixed schema and handle large volumes of data and high user loads well.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples: Document Stores like MongoDB, and Key-Value Stores like Redis and DynamoDB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Like I said earlier different databases have places they shine better and its easy to imagine one application having to use different databases for different things.&lt;/p&gt;

&lt;p&gt;In this article, I'll go over how I connected a go application to both a MySQL database and a MongoDB database step by step.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1: Setting up the Project
&lt;/h2&gt;

&lt;p&gt;First, I set up my Golang project using Go modules for dependency management. This involved initializing a new Go module and creating the necessary directory structure for the project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir muli-db-connection
cd multi-db-connection
go mod init multi-db-connection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Installing Database Drivers
&lt;/h2&gt;

&lt;p&gt;Golang uses specific drivers to interact with different databases. For MySQL, I used &lt;code&gt;go-sql-driver/mysql&lt;/code&gt;, and for MongoDB, I used &lt;code&gt;mongo-go-driver&lt;/code&gt;. I installed these drivers using the &lt;code&gt;go get&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go get -u github.com/go-sql-driver/mysql
go get go.mongodb.org/mongo-driver/mongo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Setting up the Databases
&lt;/h2&gt;

&lt;p&gt;I used Docker to run MySQL and MongoDB locally, you can download and install it from the &lt;a href="https://docs.docker.com/get-docker/"&gt;Docker website&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First I pulled the Docker images for MySQL and MongoDB from the Docker Hub.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker pull mysql:latest
docker pull mongodb/mongodb-community-server:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I ran a MySQL container with the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --name mysql-container -e MYSQL_ROOT_PASSWORD=rootpassword -d -p 3306:3306 mysql:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will set up a MySQL container with the root password &lt;code&gt;rootpassword&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then I ran a mongoDB container with the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --name mongodb-container -p 27017:27017 -d mongodb/mongodb-community-server:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Verify the containers are running by running
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see both &lt;code&gt;mysql-container&lt;/code&gt; and &lt;code&gt;mongodb-container&lt;/code&gt; listed.&lt;/p&gt;

&lt;p&gt;Access MySQL&lt;br&gt;
To access the MySQL container with docker you can run the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker exec -it mysql-container mysql -uroot -prootpassword
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;while in here you can run the following SQL commands to: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;create and use a new database
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE DATABASE mydatabase;
USE mydatabase;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;create a users table to read from later
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;note: you can type &lt;code&gt;exit&lt;/code&gt; to exit;&lt;/p&gt;

&lt;p&gt;Acess MongoDB&lt;br&gt;
To access the MongoDB container with mongosh (the MongoDB shell) you can run the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mongosh --port 27017
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4 Establishing Database Connections
&lt;/h2&gt;

&lt;p&gt;With the drivers installed and the local databases setup the next step was to establish connections to both databases. I created a &lt;code&gt;db&lt;/code&gt; package to manage my database connections. In this package, I wrote seperate functions for connecting to MySQL and MongoDB.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting to MySQL
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package db

import (
    "context"
    "log"
    "time"

    "database/sql"
    _ "github.com/go-sql-driver/mysql"

    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

func ConnectMySQL() (*sql.DB, error) {
    dsn := "root:rootpassword@tcp(localhost:3306)/mydatabase"
    db, err := sql.Open("mysql", dsn)
    if err != nil {
        log.Fatalf("Error opening database: %v", err)
        return nil, err
    }

    if err := db.Ping(); err != nil {
        log.Fatalf("Error connecting to the database: %v", err)
        return nil, err
    }

    log.Println("Connected to MySQL successfully!")
    return db, nil
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Connecting to MongoDB
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...

func ConnectMongoDB() (*mongo.Client, error) {
    clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")
    client, err := mongo.NewClient(clientOptions)
    if err != nil {
        log.Fatalf("Error creating MongoDB client: %v", err)
        return nil, err
    }

    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()

    if err := client.Connect(ctx); err != nil {
        log.Fatalf("Error connecting to MongoDB: %v", err)
        return nil, err
    }

    if err := client.Ping(ctx, nil); err != nil {
        log.Fatalf("Error pinging MongoDB: %v", err)
        return nil, err
    }

    log.Println("Connected to MongoDB successfully!")
    return client, nil
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Using the Connections
&lt;/h2&gt;

&lt;p&gt;With the connections established, the next step was to use these connections in my application. I created a simple function to demonstrate querying both databases.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "context"
    "fmt"
    "log"

    "multi-db-connection/db"
    "go.mongodb.org/mongo-driver/bson"
)

func main() {
    // Connect to MySQL
    mysqlDB, err := db.ConnectMySQL()
    if err != nil {
        log.Fatalf("Could not connect to MySQL: %v", err)
    }
    defer mysqlDB.Close()

    // Connect to MongoDB
    mongoClient, err := db.ConnectMongoDB()
    if err != nil {
        log.Fatalf("Could not connect to MongoDB: %v", err)
    }
    defer mongoClient.Disconnect(context.Background())

    // Query MySQL
    rows, err := mysqlDB.Query("SELECT id, name FROM users")
    if err != nil {
        log.Fatalf("Error querying MySQL: %v", err)
    }
    defer rows.Close()

    for rows.Next() {
        var id int
        var name string
        if err := rows.Scan(&amp;amp;id, &amp;amp;name); err != nil {
            log.Fatalf("Error scanning MySQL row: %v", err)
        }
        fmt.Printf("MySQL User: %d, %s\n", id, name)
    }

    // Query MongoDB
    collection := mongoClient.Database("testdb").Collection("users")
    cursor, err := collection.Find(context.Background(), bson.M{})
    if err != nil {
        log.Fatalf("Error querying MongoDB: %v", err)
    }
    defer cursor.Close(context.Background())

    for cursor.Next(context.Background()) {
        var user bson.M
        if err := cursor.Decode(&amp;amp;user); err != nil {
            log.Fatalf("Error decoding MongoDB document: %v", err)
        }
        fmt.Printf("MongoDB User: %v\n", user)
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6: Testing and debugging
&lt;/h2&gt;

&lt;p&gt;Testing the application involved running the main function and ensuring that both databases were queried successfully. Debugging was a crucial part of this process, as I encountered various issues such as connection timeouts, incorrect credentials, and network issues, it wasn't all smooth sailing but I guess thats where learning happens. Logging detailed error messages helped identify and resolve these problems quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Connecting to multiple databases in Golang was a challenging yet rewarding experience. It pushed me to understand the intricacies of database drivers, connection handling, and error management in Golang. This project was a significant step in my backend development journey, and I am excited to continue building on this foundation during the &lt;a href="https://hng.tech/internship"&gt;HNG Internship&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The HNG Internship has always been a beacon of learning and growth for me. While I didn't finish the internship multiple times in the past, it provided invaluable knowledge that I still use today. Now, as I embark on this new journey into backend development, I look forward to the internship being an equally enriching supplement to my learning. I am eager to tackle new challenges, learn from experienced mentors, and ultimately become a more well-rounded developer. &lt;/p&gt;

&lt;p&gt;Who knows maybe I'll be a finalist this year 🤞🏾.&lt;/p&gt;

&lt;p&gt;link to project on github:&lt;br&gt;
&lt;a href="https://github.com/vinuch/go-multi-db-connection"&gt;https://github.com/vinuch/go-multi-db-connection&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;links to the HNG Internship: &lt;br&gt;
&lt;a href="https://hng.tech/internship"&gt;https://hng.tech/internship&lt;/a&gt;, &lt;a href="https://hng.tech/hire"&gt;https://hng.tech/hire&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Do check them out, thank you!.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
