Setting up a free Minecraft PE Server

Being the amazing nerdy Dad that I am, of course I’ve done my share to introduce my kids into video gaming. Being that they are elementary age, of course I introduced them into Minecraft. Given that hey had been using an iPad for few years already, my daughter took to the game building amazing objects. My son, enjoyed it mostly because it let him destroy his sister’s creations.

What really blew their minds was when they discovered they could also play with their cousin that lived over 600 miles away. They would setup a facetime session (video chat) and then open Minecraft and play with each other. The problem was that the world they built either lived on my daughter’s iPad, or my nephews. Meaning that they couldn’t always keep working on the world when the other wasn’t online. So I set out to find a solution.

Mojang, came out with their solution to this problem by creating Realms. Now a realm is a world that Mojang will keep online and you and your friends can come and go as you wish. This was exactly the idea, however they only allow for up to 3 people connected a time and charge $4 a month to keep the world hosted. Now I know that doesn’t seem much, but $48 a year so my kids can play online and the moment I stop paying all of their creations are lost didn’t really sit well with me. So that idea was no good.

I began looking into setting up a Minecraft server, since you can download the Java jar file for free from Mojang, but I quickly discovered that this server would only work with Windows, Mac, and Linux clients. However given that they used an iPad, they used Minecraft Pocked Edition (PE), which wasn’t compatible.

After doing some googling I stumbled onto a free opensource project called PocketMine MP. A group of talented developers created an Open Source PHP based application that acts as a Minecraft PE server. BINGO! So now that I found the software, I needed someplace to put it. Well reading over the installation documents, it appears that at this moment it is primarily setup to run using Linux. Now, I’ve setup my fair share of Linux servers and clients in the past and for those that are worried, don’t be its fairly straight forward. So the server doesn’t need to be powerful, but I did want it in a place that will always be online.

So recently I’ve been growing an learning about Amazon Web Services (AWS) and cloud computing and I realized that EC2 (AWS’s virtual machine services in the cloud) has a free teir that allows me to run a Linux host with a public IP from for free for a whole year! So I decided, heck yeah I’ll use the power of the cloud to run a public Minecraft server!

So, without being too specific, you want to go signup for a free AWS account. After you do that head to EC2 and select Launch Instance. Then select the Amazon Linux AMI.

Capture

Then select the t2.micro instance. This will give you 1 CPU and 1 GB of memory.

Capture

On the next page, go to the bottom and expand the Advanced Details and then copy the below script into the User Data field. This will update the server and then download the latest version of the PocketMine-MP.

#!/bin/bash
yum update -y
mkdir /usr/local/pmmp
cd /usr/local/pmmp
wget -q -O - https://raw.githubusercontent.com/pmmp/php-build-scripts/master/installer.sh | bash -s - -r

Then head to the Configure Security Group page. Security groups are like a group of firewall rules. By default only TCP port 22 is open to allow SSH into the system. We will want to also add 19132 UDP to allow for the clients to connect to the PocketMine server.You can also open 19132 TCP if you would like to use the remote console.

Capture

Then launch the instance and you will have a running server with the latest version of PocketMine installed. All you need to do is to SSH into the server and then begin the configuration wizard by launching ./start.sh in /usr/local/pmmp/.

Missing

Okay so I wanted to let everyone know that I’m still alive. The reason that I’ve disappeared for a while is that I was reached out to about writing a book and I jumped on that opportunity. This means that the blog will likely be dark for a few months or so that I can focus on this side project. But I should be back adding new content in February.

 

Modern Public Folders: Part 1

Over the past decade of working with dozen of Exchange environments, I can say that Public Folders are that one part of Exchange that most admins wish weren’t there. Some of you newer admins or have had the benefit of being in an environment where Public Folders were underutilized likely can’t relate with these feelings. But those of us who have been working in these older environments have a hierarchy with hundred- of-thousands of folders.

Legacy Public Folders

Long ago, probably before most people in the Internet were born, Public Folders were meant to fill a gap that allowed groups to share data and information. Remember this is long before Google Drive, SharePoint and the other dozens of collaborative tools that didn’t exist.

Exchange 2010 and prior, Public Folders where hosted on their own separate unique databases. However, the databases weren’t clustered. Instead public folders where synced accrossed databases using PF replication. So the advantage to this method is that you can choose which folders are replicated to which databases. If you wanted to geo-locate data, you could force data to specific databases/servers.

The Cloud Killed Legacy Public Folders

Around the time of Exchange 2007 and 2010, there where rumors spreading about Microsoft killing off Public Folders. Why? Well there was a time that Microsoft was encouraging organizations to move their Public Folder infrastructures to SharePoint. When Microsoft realized that organizations weren’t adopting this strategy they were faced with an issue. See Microsoft wanted to encourage people to start using it’s new cloud based Exchange environments, but it didn’t want to bring Legacy Public Folders to the cloud.

Modern Public Folders

So out of necessity the Modern Public Folders where created started in Exchange 2013. So what is different?

There are no longer any Public Folder Databases.

That’s right, no Public Folder Databases. So where do my public folders go? Well Microsoft decided to create something called a Public Folder Mailbox. These mailboxes can be hosted on regular mailbox databases. Which means, the data can now be protected through Database Availability Groups.

There are two kinds of Public folder mailboxes, Primary and Secondary Hierarchy Mailboxes. There is one and only one Primary Hirearchy Mailbox. The purpose of this mailbox is to maintain the only writable copy of the Public Folder structure and permissions. Every other Public Folder Mailbox is a Secondary  Mailbox. These maintain read-only copies of the hierarchy.

Watch for the next post for strategies on working with large Modern Public Folders.

Skype for Business Custom Statuses

When it comes to Skype for Business, there isn’t much left in the client that is open to customization. But one area that is available but hidden are being able to create custom status. So what is a custom Status? Well it’s a status that stands outside of the default choices of Available, Busy, Do Not Disturb, Be Right Back, etc.

The Scenario

For example, in one environment that I’ve worked in, the organization wanted to allow an individual to set a status of In a Call. The main reason for this was that the environment wasn’t using Enterprise Voice, so there was no automatic status change for these customers. Additional statuses that where desired where a distinction of working from home. This was desired because some individuals lost access to the Location field when logging in remotely.

Creating the Custom Statuses

So how do we make this happen? First, we need to make a specially formatted XML file with our custom states. Microsoft has a great article with an example of the XML formatted file. But for this scenario I created the below XML Code.

<?xml version="1.0" encoding="UTF-8"?>
<customStates>
<customState availability="Busy" ID="1">
<activity LCID="1033">In a Call</activity>
</customState>
<customState availability="Online" ID="2">
<activity LCID="1033">Working From Home</activity>
</customState>
<customState availability="Busy" ID="3">
<activity LCID="1033">Working From Home</activity>
</customState>
</customStates>

Publishing the Custom Statuses

So now that we have our XML file what do we do with it? Next the XML file needs to get published to a secured web-server where clients can access. I chose to publish my file to a new Directory called CustomState on each of the Front-End servers. After putting the file in a directory on each of the Front-End servers, I added that Directory to the root of IIS server so that it is accessible at HTTPS://Pool.Domain.com/CustomState/CustomState.xml.

It is important that if you have a Pool, that you need to publish this file to every server. Otherwise you’re customers will get an inconsistent result depending on which server they connect to. <h1>Directing the Clients</h1> Finally, we need to let the clients know where to find the custom status file. We do this by configuring the

Set-CsClientPolicy -Identity ClientPolicy -CustomStateURL "HTTPS://Pool.Domain.com/CustomState/CustomState.xml"

The End Result

After logging off and back onto my client, the custom states are now showing as expected.

skype-custom-status
Showing the end result of creating Custom Statuses in Skype for Business

While this is a single, and basic scenario, I’d be interested to know how others are using custom statuses. Please leave a comment to share your experience.

PF Permissions

To be honest, I’ve never been a big fan of Public Folders (PFs). Actually, now that I think of it, I’ve never met an Exchange Administrator who doesn’t have a distaste for PFs. However, they are one of those things that many older and larger organizations started to used a long time ago, when it was one of the only choices for collaboration.

One of the nuances of PFs is permissions. When a Root (\) folder is created, typically us admins will setup the permissions for clients. At that point any new child item of folder inherits the permission of it’s parent folder. This works great, until you get into organizations where there can be hundreds of thousands of folders that make a giant mess.

Additionally, when you add PF permissions, the permissions do not get propagated to child folders. Of course you can use the EWS interface, however for very large trees, you will see the command timeout.

So to address this issue I made the below script. The intention of it is to set the permission on a public folder and all child directories. It is built to allow for multiple users and PF branches. This will look at the trees provided and get a list of all of the child public folders. Then it will check if the user already has permissions on the folder, and if so remove the current permissions. Why is this? Well a user can’t have more than on permission on a folder. So any attempt to add the desired permission will produce an error. So instead I strip out the current permission and then replace it with the desired permission.

Enjoy! Download

<#
.SYNOPSIS
Set the PF permissions on all children Public Folders
.DESCRIPTION

.PARAMETER PFrOOT
The path to the ROOT file that you want to set permission. This attrubte accepts multiple paths.
.PARAMETER Users
Provide the list of user
.EXAMPLE
C:\PS> .\Set-PFClientPermissions.ps1 -PFRoot ".\Folder" -Users "User1", "user2" -Perm PublishingEditor

.NOTES
Author: Joshua Wortz
Date: octover 12th, 2016
#>
paramaters(
[array]$PFRoot,
[array]$users,
[string]$Perm
)


$pfs = $pfroot | %{Get-PublicFolder $_ -Recurse}

foreach ($pf in $pfs)
{
foreach ($user in $users)
{

if (Get-PublicFolderClientPermission -User $user -Identity $pf.Identity -ErrorAction:SilentlyContinue)
{
Get-PublicFolderClientPermission -User $user -Identity $pf.Identity | Remove-PublicFolderClientPermission -Confirm:$false

}

Add-PublicFolderClientPermission -Identity $pf.Identity -AccessRights $Perm -User $user -ErrorAction:Stop

}
}

Clean-Logs

For those of us who have been administering Windows web based servers know that one feature that IIS is known for is not rolling over its logs. Many admins have left logging off when not needing to debug or troubleshoot to work around this. In many enterprise environments, it’s import to maintain these logs to review for security issues.

So I initially created this script to trim the IIS logs on exchange servers. it will search for the exchange servers on your environment and remotely query IIS to locate the log directories. After which it will delete any logs older than the configured amount of days.

When Exchange 2013 came out, I updated the script to also truncate the Exchange logs, since Exchange 2013 was created with a large amount of logging, that again doesn’t truncate. The script will also locate the Exchange log files and truncate those logs as well.

Finally at the end, the script will send an email report of all files deleted from each server for record keeping. Follow the link below to download.

Download


&lt;#
.SYNOPSIS
Used to trim IIS logs on Exchange 2013 servers
.DESCRIPTION
Because of the increased level of logging in Exchange 2013 I developed this script
to locate and truncate log files over a certain day length.
This script will find log files in the Default IIS logging location
and in the Exchange installation location
.NOTES
File Name : Clean-Logs.ps1
Author : Joshua Wortz (v1.0)
Prerequisite : PowerShell V2 over Vista and upper.
Versoion History : v1.0 23rd May 2015 : First Edition

#&gt;
param([switch]$Exchange)

$From = "From@domain.com"
$To = "To@domain.com"
$SMTPServer = "SMTPServer"

$days=30 #You can change the number of days here
#$IISLogPath ="C:\inetpub\logs"

Write-Host "Removing IIS and Exchange logs; keeping last" $days "days"

function Out-FileForce {
PARAM($path)
PROCESS
{
if(Test-Path $path)
{
Out-File -inputObject $_ -append -filepath $path
}
else
{
new-item -force -path $path -value $_ -type file
}
}
}

#Locating and Removing old Logs
Function CleanLogfiles($TargetFolder, $Server)
{
$targetfolder = $targetfolder -replace "%SystemDrive%", "c:"
$TargetServerFolder = "\\$($Server)\" + $TargetFolder.split(':')[0] + "$" + $TargetFolder.split(':')[1]
Write-Host $TargetServerFolder
if (Test-Path $TargetServerFolder) {
$Now = Get-Date
$LastWrite = $Now.AddDays(-$days)
$Files = Get-ChildItem $TargetServerFolder -Include *.log,*.blg -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}

$files | Remove-Item -ErrorAction SilentlyContinue | out-null

$colItems = $files | Measure-Object -property length -sum

[string]$sum = "{0:N2}" -f ($colItems.sum / 1MB) + " MB"

$sum

}
Else {
Write-Host "The folder $TargetServerFolder doesn't exist! Check the folder path!" -ForegroundColor "red"
}

}
#gets the name of the Ex2015 servers
Function Get-ExchangeServerInDomain {

$configNC=([ADSI]"LDAP://RootDse").configurationNamingContext
$search = new-object DirectoryServices.DirectorySearcher([ADSI]"LDAP://$configNC")
$objectClass = "objectClass=msExchExchangeServer"
$serialNumber = "serialNumber=Version 15.*"
$name = "name=DC*"#modify if naming schema is different
$search.Filter = "(&amp;($objectClass)($serialNumber)($name))"
$search.PageSize=1000
[void] $search.PropertiesToLoad.Add("name")
[void] $search.PropertiesToLoad.Add("serialNumber")
$search.FindAll() | %{$_.Properties.name[0]}

}
[string]$Body = $null

#Gets list of Servers
[array]$Servers = Get-ExchangeServerInDomain

foreach ($Server In $Servers) {
[array]$logs = $null

#Queries IIS for log paths for Each IIS Site on Server
$IISLogPaths = Invoke-Command -ComputerName ($Server) -ScriptBlock {get-website | %{$_.logfile.Directory}}
$Body += "&lt;H1&gt;$Server&lt;/H1&gt;"
#Delete log files from each IIS path
foreach ($Path in $IISLogPaths)
{

$logs += $path | select @{N="Path";e={$_}}, @{N="Size Deleted";e={$( CleanLogfiles -TargetFolder $Path -server $Server)}}

}

if($Exchange -eq $true)
{
#Get Path of Exchange Installation on remote server
$objReg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $Server)
$objRegKey= $objReg.OpenSubKey("SOFTWARE\\Microsoft\\ExchangeServer\\v15\\Setup\\")
[array]$ExchangeLoggingPath = $objRegkey.GetValue("MSiInstallPath") + "Logging\"
$exchangeloggingpath += "D:\Exchange\Logs"

$logs += $exchangeloggingpath | select @{N="Path";e={$_}}, @{N="Size Deleted";e={$(CleanLogfiles -TargetFolder $_ -server $Server)}}

$body += $logs | convertto-html -fragment
}

}

$head = @'
&lt;style&gt;
body { background-color:#dddddd;
font-family:Tahoma;
font-size:12pt; }
td, th { border:1px solid black;
border-collapse:collapse; }
th { color:white;
background-color:black; }
table, tr, td, th { padding: 2px; margin: 0px }
table { margin-left:50px; }
&lt;/style&gt;
'@

[string]$html = convertto-html -Head $head -Body $body #| Out-File $reportFile -Force

Send-MailMessage -SmtpServer $SMTPServer -To $to -From $From -Body $html -Subject "IIS Logs Deleted" -BodyAsHtml