Attach an AWS EBS volume to a Linux server

Format and mount the volume

List the available disk devices and their mount points

lsblk

The nvme1n1 volume is not yet mounted

Create a partition on the volume

List the existing partitions

fdisk -l

Create a new partition

fdisk /dev/nvme1n1
# enter n to create a new partition and follow the defaults to maximize the drive space used 
# enter p tp view the partition table
# enter w to write the partition table to the disk

Check the partition list

lsblk

Detect the new partition with

partprobe

If there is a file system on the partition to determine the file system of the volume

file -s /dev/nvme1n1p1

“data” means no file system

If there is no file system on the volume, create one

mkfs -t xfs /dev/nvme1n1p1
# If the partition already has a files system and you want to overwrite it use the xfs -f option
mkfs -t xfs -f /dev/nvme1n1p1

If the mkfs tool is not found, install it with yum install xfsprogs

Create a mount point

Create a directory where the volume will be mounted

mkdir /data

Mount the volume to the directory

mount /dev/nvme1n1p1 /data

Automatically mount the volume after reboot

The mounting above will not be retained after a reboot. To keep the volume mounted after a reboot add am entry to the /etc/fstab file

Make a safety copy of the original fstab file

cp /etc/fstab /etc/fstab.orig

Use blkid to find the UUID of the device

blkid

# On Ubuntu 18.04
lsblk -o +UUID

Open the /etc/fstab file in an editor

vim /etc/fstab

Add an entry to the /etc/fstab file for the volume

UUID=7c6cb20b-ada0-4cd7-9c3a-342d6faf87a2  /data  xfs  defaults,nofail  0  2
  • UUID
  • Mount point
  • file system
  • recommended file system mount options. The nofail option will allow this server to boot even if the volume is not available. On Debian derivatives, including earlier than Ubuntu 16.04 nobootwait is also necessary

To test if the file entry is correct unmount the volume and use the /etc/fstab to mount it again

umount /data
mount -a

If there are no errors, the file should be correct.

To list the directory sizes

du -sh *

To empty a file

cat /dev/null > ./MY_LARGE_LOG_FILE

Check the load on the computer

uptime

23:58:50 up 318 days, 16:32, 1 user, load average: 0.03, 5.34, 18.68

The load averages are from the past 1, 5, and 15 minutes

has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource

When your website calls the Socket.IO backend API from another domain, the browser console displays the error message

Access to XMLHttpRequest at ‘http://…:3000/socket.io/?EIO=3&transport=polling&t=N7Y-Fot’ from origin ‘http://….com’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

To enable Cross-origin resource sharing add the code to the top of your Socket.IO server.js file

const server = require('express')();

// require 'cors'
const cors = require('cors')
// Add CORS before any other routing
server.use(cors());

const http = require('http').createServer(server);
const io = require('socket.io')(http);

Before building the application install the cors package

npm install cors

Uncaught TypeError: _helpers_formUtil__WEBPACK_IMPORTED_MODULE_6___default.a is not a constructor

When you import a Phaser 3 module and run the Node.js web application the following error is displayed

Uncaught TypeError: _helpers_formUtil__WEBPACK_IMPORTED_MODULE_6___default.a is not a constructor

Make sure the imported module and all dependent modules imported by that module has the following class definition format

export default class MY_CLASS_NAME {

Creating a multiplayer online card game with Node.js and Phaser 3

As the world is locked down due to the COVID-19 Corona Virus, we are quarantined at home. We miss the company of our families and friends, so online games are the only option to play together. We are going to create an online multiplayer game that can be used for any tabletop gameplay.

The frontend is going to be JavaScript, Node.js, Phaser3, the backend is Express and Socket.IO.

The framework for this game came from the great tutorial at How to Build a Multiplayer Card Game with Phaser 3, Express, and Socket.IO

Install a web server for development

I have installed XAMPP from https://www.apachefriends.org/index.html

The home directory where the index.html should be is at C:\xampp\htdocs

Install Node.js

Install the latest version of Node.js from https://nodejs.org/en/download/

Install Phaser3

Install Phaser 3 based on http://phaser.io/download/stable as of writing with

npm install phaser@3.22.0

The getting started guide on Phaser 3 is at Getting Started with Phaser 3

A great game tutorial is at Making your first Phaser 3 game

The multiplayer online game development

Client

To test the client on your workstation, start the Node.js client from a terminal window to display the web page for the players.

cd client
npm install
npm start

The default browser opens with the http://localhost:8080/ address.

Server

To test the server on your workstation start the multiplayer server in another terminal window

cd into the root directory above the client. The next command will ask questions and create a new package.json file

cd server
npm init

Install Express, Socket.IO, and Nodemon

npm install --save express socket.io nodemon

Start the server

npm run start
or
node server.js

Build the application

Stop the client development server, otherwise you will get the error message

Error: EPERM: operation not permitted, lstat ‘…\client\dist\src\assets’

Build the client application

cd client
npm update
npm run build

Deploy the application on the workstation

Copy the assets into the dist directory

cd client
mkdir -p dist/src/assets
cp src/assets/* dist/src/assets

Copy the contents of the client\dist directory to the webserver

mkdir -p C:/xampp/htdocs/rummy
cp -r dist/* C:/xampp/htdocs/rummy

Start the Express server

To provide the Socket.IO functionality in the root of the game development directory execute

cd server
npm run start

Test the multiplayer application in the local network

Use your workstation as the test server and connect to it from another computer.

Set the Socket.IO server URL

To be able to connect to the same Express server from the workstation and from another computer on the same network change the Socket.IO URL in the client/src/scenes/game.js file.

this.socket = io('http://MY_COMPUTER_IP:3000');

Expose the Express server on your workstation to the local network

Open port 3000 in the Windows firewall.

Start the webserver

Open the XAMPP Control Panel and click the Apache Start button

Open the website

In a web browser navigate to http://MY_COMPUTER_IP/rummy/

Build the Docker image

Based on the great post at Dockerizing a Node.js web app

Create a Dockerfile in the server directory

FROM node:12

# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
# The wildcard will copy both the package.json AND package-lock.json files (npm@5+)
COPY package*.json ./

RUN npm install
# If you are building your code for production
# RUN npm ci --only=production

# Copy all files
COPY . .

# The server listens on port 3000 by default
EXPOSE 3000

CMD [ "node", "server.js" ]

Build the server Docker image

cd server
docker build -t robbers-rummy-server .

Create a Dockerfile in the client directory. We will use a two-stage build process to make the final image as lean as possible. We build the application in a Node.js container and run it in an Nginx container.

FROM node:12 as builder

# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./

RUN npm install
# If you are building your code for production
# RUN npm ci --only=production

# Bundle app source
COPY . .

RUN npm update

RUN npm run build

# Create asset directory
RUN mkdir -p dist/src/assets

# Copy the images to the dist folder
COPY src/assets/* dist/src/assets/

FROM nginx:alpine as runner

WORKDIR /usr/share/nginx/html

COPY --from=builder usr/src/app/dist/* ./

# Copy the images from the source
RUN mkdir -p src/assets

COPY --from=builder /usr/src/app/src/assets/* src/assets/

EXPOSE 80

Build the client Docker image

cd client
docker build -t robbers-rummy .

Launch the Docker containers

Start the server container from any directory

docker run -p 3000:3000 -d robbers-rummy-server

Start the client website container from any directory

 docker run -p 80:80  -d robbers-rummy

Stop the Docker conainers

Get the container IDs

docker ps

Stop and remove the containers using the container IDs

docker stop MY_CONTAINER_ID
docker rm MY_CONTAINER_ID

Use Docker Compose

To launch the server and the client website together we will create a docker-compose.yml file in the root of the application

version: '3'
services:
  api:
    image: robbers-rummy-server
    build: .
    networks:
      - backend
    ports:
      - "3000:3000"

  web-cli:
    image: robbers-rummy
    networks:
      - backend
    ports:
      - "80:80"

networks:
  backend:
    driver: bridge

Start the containers with Docker Compose from the application root directory

docker-compose up -d

To stop the containers launched with Docker Compose from the application root directory

docker-compose down

Host the application in AWS

The application consists of two parts: a static website with the game Javascript files, and the Express server to run Socket.IO

We will host the static website in AWS S3, and the server Docker container in an AWS ECS Fargate cluster.

Migrating from Chef Client version 13 to 15

Syntax changes

There are breaking changes between Chef Client version 13 and the newer versions, make sure you update your Chef cookbooks to make them work with the new version of the Chef Client.

ResourceSince versionOld syntaxNew syntaxNotes
loggerClient 14.0keyword, cannot use it as a variable or parameter name
windows_firewall_rule resourceClient 14.7localportlocal_portMoved from the Windows cookbook to the Chef cookbook

Computer failed to join domain from its current workgroup ‘WORKGROUP’ with following error message: The system cannot open the device or file specified.

When you use PowerShell to join a Windows server to the domain make sure the -OUPath is correct.

Computer failed to join domain from its current workgroup ‘WORKGROUP’ with following error message: The system cannot open the device or file specified.

In this case we wanted to place the joined computers in the Computers folder, so no OUPath specification is necessary. The solution was to omit the -OUPath option from the command:

Add-Computer -DomainName $domain -Credential $credential -Server $domaincontroller -ComputerName $old_computername -NewName $new_computername

Computer ‘…’ failed to join domain. The value provided as the current password is incorrect.

Computer ‘…’ failed to join domain ‘…’ from its current workgroup ‘WORKGROUP’ with following error message: Unable to update the password. The value provided as the current password is incorrect.

If you can join the computer to a domain using the UI, but the PowerShell script fails with the error message above, make sure you add the name of the domain to the username that joins the computer to the domain.

domain\\username

When you use the UI, Windows knows the user belongs to the new domain. The configuration tools run as a local admin, so you need to specify the name of the domain with the user name.