<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.seaoffate.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Wikisailor</id>
	<title>Sea of Fate - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.seaoffate.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Wikisailor"/>
	<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php/Special:Contributions/Wikisailor"/>
	<updated>2026-06-05T22:18:12Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1547</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1547"/>
		<updated>2026-05-16T13:14:24Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Software installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
The first Minecraft host needs to have enough resources to run the JVM and the server but as it just a vanilla server the specification does not need to be excessive. The table shows the highlights.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;br /&gt;
&lt;br /&gt;
===Velocity Installation===&lt;br /&gt;
&lt;br /&gt;
The Velocity server VM does not need to be especially high because all it needs to do is accept connections and forward them on to the relevant host and any associated functions like handle logon, bans and etc. Unlike the cherry host that we just setup the base specification from the Debian template needs to be cut down a bit and does not need a extra swap file or anything special.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 1 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 1GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Storage || 32GB ||  &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Vangueria ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.29 ||&lt;br /&gt;
|}&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
As there is no additions to the VM&#039;s specification there is no hardware to configure so we can get straight to the software installation. So the well known update/upgrade and the packages can be installed with&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless htop screen wget jq curl&lt;br /&gt;
Once the dependencies are installed, we create a dedicated application directory and use an automated script to identify the most recent build of Velocity 3.4.0. This ensures we are not relying on hardcoded links that may expire.&lt;br /&gt;
 mkdir ~/velocity &amp;amp;&amp;amp; cd ~/velocity&lt;br /&gt;
 export PROJECT=&amp;quot;velocity&amp;quot;&lt;br /&gt;
 export VERSION=&amp;quot;3.4.0-SNAPSHOT&amp;quot;&lt;br /&gt;
 export LATEST_BUILD=$(curl -s https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION} | jq &#039;.builds[-1]&#039;)&lt;br /&gt;
 wget -O ~/velocity/velocity.jar &amp;quot;https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION}/builds/${LATEST_BUILD}/downloads/${PROJECT}-${VERSION}-${LATEST_BUILD}.jar&amp;quot;&lt;br /&gt;
The initial boot of Velocity is performed to generate the necessary configuration files. We launch it with a 512MB heap size and then shut it down gracefully using the end command once the prompt appears.&lt;br /&gt;
 java -Xms512M -Xmx512M -jar velocity.jar&lt;br /&gt;
&lt;br /&gt;
====Proxy Configuration and Routing====&lt;br /&gt;
&lt;br /&gt;
The primary configuration for the proxy is handled within the velocity.toml file. This file dictates how the proxy listens for incoming traffic and how it maps domain names to internal IP addresses. We edit this file to ensure the proxy is listening on all interfaces and that it is using the modern forwarding protocol.&lt;br /&gt;
 nano ~/velocity/velocity.toml&lt;br /&gt;
Modify these specific lines:&lt;br /&gt;
* Bind Address: bind = &amp;quot;0.0.0.0:25565&amp;quot; (Allows it to hear traffic from pfSense).&lt;br /&gt;
* Forwarding Mode: player-info-forwarding-mode = &amp;quot;modern&amp;quot; (This is the most secure protocol for 2026).&lt;br /&gt;
* ping-passthrough should be set to ALL. This is to ensure the server list on the Minecraft client correctly displays the status and version of the backend servers&lt;br /&gt;
* Server List: Scroll down to the [servers] section:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[servers]&lt;br /&gt;
 cherry = &amp;quot;192.168.100.30:25565&amp;quot;&lt;br /&gt;
 apple = &amp;quot;192.168.100.35:25565&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 [servers]&lt;br /&gt;
 try = [&lt;br /&gt;
    &amp;quot;cherry&amp;quot;&lt;br /&gt;
 ]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Forced Hosts: This tells the proxy which server to pick based on the URL the player typed:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[forced-hosts]&lt;br /&gt;
 &amp;quot;cherry.seaoffate.net&amp;quot; = [&amp;quot;cherry&amp;quot;]&lt;br /&gt;
 &amp;quot;apple.seaoffate.net&amp;quot; = [&amp;quot;apple&amp;quot;]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Save and close the file. next we need a start.sh file for Velocity &lt;br /&gt;
 nano ~/velocity/start.sh&lt;br /&gt;
copy the following into the file&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Vangueria Proxy ---&amp;quot;&lt;br /&gt;
     java -Xms512M -Xmx512M \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar velocity.jar&lt;br /&gt;
     echo &amp;quot;--- Proxy stopped. Restarting in 5s ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
To make the script executable &lt;br /&gt;
 chmod +x ~/velocity/start.sh&lt;br /&gt;
At this point the since Vangueria is now set to Modern Forwarding, Cherry will reject all connections until it has the forwarding.secret. the secret can be obtained with the command&lt;br /&gt;
 cat ~/velocity/forwarding.secret&lt;br /&gt;
Copy the code to a safe location because we will need it to setup cherry (and apple). then we should be able to finally start the proxy with the start.sh&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now we move to cherry to setup it&#039;s ability to receive connections from Vangueria. &lt;br /&gt;
&lt;br /&gt;
====Configuring Cherry To Accept Proxied Connections====&lt;br /&gt;
&lt;br /&gt;
To complete the integration between the proxy and the backend, Cherry must be transitioned from a standalone Vanilla server to a &amp;quot;Proxy-Aware&amp;quot; host. Because Vanilla Minecraft does not natively support Velocity’s Modern Forwarding (the security handshake), we use the Fabric Loader as a lightweight wrapper. This allows us to install a bridge mod that validates the secret key without changing the gameplay experience.The transition of Cherry involves three main phases: installing the Fabric environment, adding the bridge mods, and configuring the security handshake to match Vangueria.&lt;br /&gt;
&lt;br /&gt;
First, we must stop the existing server and install the Fabric transition layer. This replaces the standard Mojang launcher with a version capable of loading the security bridge. We need to download the Fabric Installer and then Install Fabric for the 1.21.1 environment.&lt;br /&gt;
 cd ~/minecraft_server&lt;br /&gt;
 wget https://maven.fabricmc.net/net/fabricmc/fabric-installer/1.0.1/fabric-installer-1.0.1.jar&lt;br /&gt;
 java -jar fabric-installer-1.0.1.jar server -mcversion 1.21.1 -downloadMinecraft&lt;br /&gt;
Once complete, the installer will have created a new file named fabric-server-launch.jar. This is now the primary entry point for the server.&lt;br /&gt;
&lt;br /&gt;
To install the Security Bridge we require two specific components in the mods folder: the Fabric API (the library that allows mods to interact with the game engine) and FabricProxy-Lite (the specific mod that handles the Velocity secret key). It is vital to use version-matched JARs for 1.21.1 to ensure stability.&lt;br /&gt;
 mkdir -p ~/minecraft_server/mods&lt;br /&gt;
 wget -O ~/minecraft_server/mods/FabricProxy-Lite.jar https://github.com/OKTW-Network/FabricProxy-Lite/releases/download/v2.10.1/FabricProxy-Lite-2.10.1.jar&lt;br /&gt;
 wget -O ~/minecraft_server/mods/fabric-api.jar https://github.com/FabricMC/fabric-api/releases/download/0.116.11%2B1.21.1/fabric-api-0.116.11+1.21.1.jar&lt;br /&gt;
&lt;br /&gt;
To configure the handshake after placing the mods, we must run the server once to generate the configuration structure, then shut it down to inject the secret.&lt;br /&gt;
Update start.sh to point to fabric-server-launch.jar instead of server.jar&lt;br /&gt;
 sed -i &#039;s/server.jar/fabric-server-launch.jar/&#039; start.sh&lt;br /&gt;
Initial run to generate config (Type &#039;stop&#039; once the &#039;Done&#039; message appears)&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now, we create the configuration file and link it to Vangueria. This is where we ensure the backend only trusts traffic coming from our proxy.&lt;br /&gt;
 mkdir -p ~/minecraft_server/config&lt;br /&gt;
 nano ~/minecraft_server/config/FabricProxy-Lite.toml&lt;br /&gt;
Paste the following configuration into the file, ensuring the secret matches the one obtained from Vangueria:&lt;br /&gt;
 enabled = true&lt;br /&gt;
 hackOnlineMode = true&lt;br /&gt;
 secret = &amp;quot;PASTE_YOUR_VANGUERIA_SECRET_HERE&amp;quot;&lt;br /&gt;
The final step is to adjust the server.properties file. Because Vangueria handles the official Mojang authentication at the &amp;quot;front door,&amp;quot; the backend server must be set to offline mode to allow the proxy to pass the authenticated user data through.&lt;br /&gt;
 sed -i &#039;s/online-mode=true/online-mode=false/&#039; server.properties&lt;br /&gt;
With the configuration complete, the server should be launched inside a named screen session to ensure it remains active.&lt;br /&gt;
 screen -S minecraft ./start.sh&lt;br /&gt;
We should now change the Pfsense port forward rule to forward traffic to the 192.168.100.29 (IP address of Vangueria) and then connecting a client from a laptop outside of Pfsense and using the address cherry.seaoffate.net, we can try using the IP address of the Pfsense WAN port but it may not work (if the default server is set to cherry it may connect)&lt;br /&gt;
&lt;br /&gt;
===Additional Options===&lt;br /&gt;
&lt;br /&gt;
There are a few additional considerations that will make the servers run more reliably. The first is thing that needs to be done is to run the server in a screen so that there does not need to be a SSH session to be running. The following will start a screen called minecraft and will execute the start.sh command. &lt;br /&gt;
 screen -S minecraft ./start&lt;br /&gt;
To exit the minecraft screen and return to the main SSH type ctrl + a and then d, the minecraft screen can be reloaded with the command &lt;br /&gt;
 screen -r minecraft&lt;br /&gt;
The next thing that we will need to do is to have the minecraft server start whenever the host reboots. So we need to add a cron tab to the start.sh&lt;br /&gt;
 crontab -e&lt;br /&gt;
Select nano if asked then add the line &lt;br /&gt;
 @reboot screen -dmS minecraft /home/nigel/minecraft_server/start.sh&lt;br /&gt;
&lt;br /&gt;
The next thing is not a minecraft helper exactly but it will be useful as a reminder in the future. When a user logs on to the host the message of the day will be displayed to add simple notes to the message we can simply edit the motd with the command&lt;br /&gt;
 sudo nano /etc/motd&lt;br /&gt;
&lt;br /&gt;
===Adding a second Minecraft server Apple===&lt;br /&gt;
&lt;br /&gt;
Now that we have the basic setup with potential for multiple hosts we will need to create at least one more so that we can prove the proxy works as intended. The next server will be a different version with some mods. As soon as we start adding mods to a Minecraft world they will use more resources so we will need the next host to be a bit better specified.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 5 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 12GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 150GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Apple||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.35 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
&lt;br /&gt;
As we did with the cherry host earlier we need to configure the hardware changes that have been made on the basic specification like adding the Lexar HD as the swap file. We must stop using the swap partition on the primary drive so we can move it out of the way. Turn off all swap.&lt;br /&gt;
 sudo swapoff -a&lt;br /&gt;
Since your swap partition (sda3) is at the end of the disk, it acts as a &amp;quot;blocker.&amp;quot; We need to delete it and the root partition, then recreate the root partition to fill the entire space.&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
* Type p to print the table (confirming sda2 is root and sda3 is swap).&lt;br /&gt;
* Type d then 3 to delete the swap partition.&lt;br /&gt;
* Type d then 2 to delete the root partition (Don&#039;t worry, the data stays in the blocks).&lt;br /&gt;
* Step B: Recreate and Expand&lt;br /&gt;
* Type n for a new partition.&lt;br /&gt;
* Type p for Primary. Note if disk is using a GPT (GUID Partition Table) there will be no P option, primary partitions only exist in the old MBR style of disks&lt;br /&gt;
* Type 2 for Partition number 2.&lt;br /&gt;
* Press Enter for the default Start Sector (it must match the old start sector of sda2).&lt;br /&gt;
* Press Enter for the default End Sector (this will now jump to the end of the 150GB disk).&lt;br /&gt;
* CRITICAL: When it asks &amp;quot;Do you want to remove the signature?&amp;quot;, type N.&lt;br /&gt;
* Type w to write changes and exit.&lt;br /&gt;
Now, reboot to make sure the kernel is looking at the new 150GB table entry.&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
Once you log back in, expand the actual data &amp;quot;container&amp;quot; (the ext4 filesystem) to fill that new partition:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
Now that the main drive is expanded, let&#039;s get that high-speed swap set up on your 16GB secondary disk.&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
We need to update /etc/fstab so your VM knows where to find its memory &amp;quot;safety net&amp;quot; on every boot.&lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Look for the line that mentions the old swap (it likely mentions sda3 or a long UUID string). Delete that line or put a # at the start of it. Add this new line at the bottom:&lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
Save and exit. Then to confirm the changes have been made use the following commands to show the new sda2 disk size and the swap disk&lt;br /&gt;
 df -h&lt;br /&gt;
 free -h&lt;br /&gt;
&lt;br /&gt;
====Software installation====&lt;br /&gt;
&lt;br /&gt;
Since Apple is a fresh VM, we need to ensure the underlying Debian OS is fully patched and has the necessary build tools and repositories before we drop a massive modpack into it. Modern modpacks like FTB University rely heavily on Java 21 or Java 25, so we will set that foundation now. First, we refresh the local package index and upgrade any existing system components. Update package lists and upgrade system and install essential utilities for file management and monitoring&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
 sudo apt install -y htop screen wget curl jq unzip zip&lt;br /&gt;
Install Java 25 and verify the version to ensure it&#039;s active&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless&lt;br /&gt;
 java -version&lt;br /&gt;
with the JRE installed we can now pull the explicit API endpoint for the FTB University installer. We will use the -JLO flags with curl. This tells it to follow redirections, process headers properly, and save the binary with its true system filename so the metadata doesn&#039;t drop.&lt;br /&gt;
 mkdir ~/ftb_university&lt;br /&gt;
 cd ~/ftb_university&lt;br /&gt;
 curl -JLO &amp;quot;https://api.feed-the-beast.com/v1/modpacks/public/modpack/108/latest/server/linux&amp;quot;&lt;br /&gt;
When the file finirm ~/ftb_university/serverinstall_108_*shes downloading, it will have a specific auto-generated string name based on the pack ID. Let&#039;s make it executable and kick off the automated build process&lt;br /&gt;
 chmod +x serverinstall_108_*&lt;br /&gt;
 ./serverinstall_108_* --auto&lt;br /&gt;
Assuming the automated build script successfully assembled the library trees, we can clear the raw installation binaries to save block space. &lt;br /&gt;
  rm ~/ftb_university/serverinstall_108_*&lt;br /&gt;
We need to generate the basic runtime parameters so the engine treats your backend initialization correctly. We need accept the core EULA agreement before the server can start and Disable Mojang online lookup to yield authentication control to Vangueria.&lt;br /&gt;
 echo &amp;quot;eula=true&amp;quot; &amp;gt; ~/ftb_university/eula.txt&lt;br /&gt;
 printf &amp;quot;online-mode=false\nmotd=FTB University Home\nallow-flight=true\nmax-tick-time=180000&amp;quot; &amp;gt; ~/ftb_university/server.properties&lt;br /&gt;
We will launch the first server loop. Forge will map out the dimensions and establish the baseline mod settings.&lt;br /&gt;
 ./run.sh&lt;br /&gt;
Since this is a clean workspace, the installer script will start downloading the specific runtime libraries. Watch the console scroll past the mod registry logs. Let the text settle completely until it opens up the standard interactive game prompt (&amp;gt;). Once you see that prompt, type stop and hit Enter to close down the thread cleanly. This will finalize our asset paths so we can secure the proxy sync.&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1546</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1546"/>
		<updated>2026-05-16T10:58:43Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Software installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
The first Minecraft host needs to have enough resources to run the JVM and the server but as it just a vanilla server the specification does not need to be excessive. The table shows the highlights.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;br /&gt;
&lt;br /&gt;
===Velocity Installation===&lt;br /&gt;
&lt;br /&gt;
The Velocity server VM does not need to be especially high because all it needs to do is accept connections and forward them on to the relevant host and any associated functions like handle logon, bans and etc. Unlike the cherry host that we just setup the base specification from the Debian template needs to be cut down a bit and does not need a extra swap file or anything special.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 1 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 1GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Storage || 32GB ||  &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Vangueria ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.29 ||&lt;br /&gt;
|}&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
As there is no additions to the VM&#039;s specification there is no hardware to configure so we can get straight to the software installation. So the well known update/upgrade and the packages can be installed with&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless htop screen wget jq curl&lt;br /&gt;
Once the dependencies are installed, we create a dedicated application directory and use an automated script to identify the most recent build of Velocity 3.4.0. This ensures we are not relying on hardcoded links that may expire.&lt;br /&gt;
 mkdir ~/velocity &amp;amp;&amp;amp; cd ~/velocity&lt;br /&gt;
 export PROJECT=&amp;quot;velocity&amp;quot;&lt;br /&gt;
 export VERSION=&amp;quot;3.4.0-SNAPSHOT&amp;quot;&lt;br /&gt;
 export LATEST_BUILD=$(curl -s https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION} | jq &#039;.builds[-1]&#039;)&lt;br /&gt;
 wget -O ~/velocity/velocity.jar &amp;quot;https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION}/builds/${LATEST_BUILD}/downloads/${PROJECT}-${VERSION}-${LATEST_BUILD}.jar&amp;quot;&lt;br /&gt;
The initial boot of Velocity is performed to generate the necessary configuration files. We launch it with a 512MB heap size and then shut it down gracefully using the end command once the prompt appears.&lt;br /&gt;
 java -Xms512M -Xmx512M -jar velocity.jar&lt;br /&gt;
&lt;br /&gt;
====Proxy Configuration and Routing====&lt;br /&gt;
&lt;br /&gt;
The primary configuration for the proxy is handled within the velocity.toml file. This file dictates how the proxy listens for incoming traffic and how it maps domain names to internal IP addresses. We edit this file to ensure the proxy is listening on all interfaces and that it is using the modern forwarding protocol.&lt;br /&gt;
 nano ~/velocity/velocity.toml&lt;br /&gt;
Modify these specific lines:&lt;br /&gt;
* Bind Address: bind = &amp;quot;0.0.0.0:25565&amp;quot; (Allows it to hear traffic from pfSense).&lt;br /&gt;
* Forwarding Mode: player-info-forwarding-mode = &amp;quot;modern&amp;quot; (This is the most secure protocol for 2026).&lt;br /&gt;
* ping-passthrough should be set to ALL. This is to ensure the server list on the Minecraft client correctly displays the status and version of the backend servers&lt;br /&gt;
* Server List: Scroll down to the [servers] section:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[servers]&lt;br /&gt;
 cherry = &amp;quot;192.168.100.30:25565&amp;quot;&lt;br /&gt;
 apple = &amp;quot;192.168.100.35:25565&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 [servers]&lt;br /&gt;
 try = [&lt;br /&gt;
    &amp;quot;cherry&amp;quot;&lt;br /&gt;
 ]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Forced Hosts: This tells the proxy which server to pick based on the URL the player typed:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[forced-hosts]&lt;br /&gt;
 &amp;quot;cherry.seaoffate.net&amp;quot; = [&amp;quot;cherry&amp;quot;]&lt;br /&gt;
 &amp;quot;apple.seaoffate.net&amp;quot; = [&amp;quot;apple&amp;quot;]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Save and close the file. next we need a start.sh file for Velocity &lt;br /&gt;
 nano ~/velocity/start.sh&lt;br /&gt;
copy the following into the file&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Vangueria Proxy ---&amp;quot;&lt;br /&gt;
     java -Xms512M -Xmx512M \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar velocity.jar&lt;br /&gt;
     echo &amp;quot;--- Proxy stopped. Restarting in 5s ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
To make the script executable &lt;br /&gt;
 chmod +x ~/velocity/start.sh&lt;br /&gt;
At this point the since Vangueria is now set to Modern Forwarding, Cherry will reject all connections until it has the forwarding.secret. the secret can be obtained with the command&lt;br /&gt;
 cat ~/velocity/forwarding.secret&lt;br /&gt;
Copy the code to a safe location because we will need it to setup cherry (and apple). then we should be able to finally start the proxy with the start.sh&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now we move to cherry to setup it&#039;s ability to receive connections from Vangueria. &lt;br /&gt;
&lt;br /&gt;
====Configuring Cherry To Accept Proxied Connections====&lt;br /&gt;
&lt;br /&gt;
To complete the integration between the proxy and the backend, Cherry must be transitioned from a standalone Vanilla server to a &amp;quot;Proxy-Aware&amp;quot; host. Because Vanilla Minecraft does not natively support Velocity’s Modern Forwarding (the security handshake), we use the Fabric Loader as a lightweight wrapper. This allows us to install a bridge mod that validates the secret key without changing the gameplay experience.The transition of Cherry involves three main phases: installing the Fabric environment, adding the bridge mods, and configuring the security handshake to match Vangueria.&lt;br /&gt;
&lt;br /&gt;
First, we must stop the existing server and install the Fabric transition layer. This replaces the standard Mojang launcher with a version capable of loading the security bridge. We need to download the Fabric Installer and then Install Fabric for the 1.21.1 environment.&lt;br /&gt;
 cd ~/minecraft_server&lt;br /&gt;
 wget https://maven.fabricmc.net/net/fabricmc/fabric-installer/1.0.1/fabric-installer-1.0.1.jar&lt;br /&gt;
 java -jar fabric-installer-1.0.1.jar server -mcversion 1.21.1 -downloadMinecraft&lt;br /&gt;
Once complete, the installer will have created a new file named fabric-server-launch.jar. This is now the primary entry point for the server.&lt;br /&gt;
&lt;br /&gt;
To install the Security Bridge we require two specific components in the mods folder: the Fabric API (the library that allows mods to interact with the game engine) and FabricProxy-Lite (the specific mod that handles the Velocity secret key). It is vital to use version-matched JARs for 1.21.1 to ensure stability.&lt;br /&gt;
 mkdir -p ~/minecraft_server/mods&lt;br /&gt;
 wget -O ~/minecraft_server/mods/FabricProxy-Lite.jar https://github.com/OKTW-Network/FabricProxy-Lite/releases/download/v2.10.1/FabricProxy-Lite-2.10.1.jar&lt;br /&gt;
 wget -O ~/minecraft_server/mods/fabric-api.jar https://github.com/FabricMC/fabric-api/releases/download/0.116.11%2B1.21.1/fabric-api-0.116.11+1.21.1.jar&lt;br /&gt;
&lt;br /&gt;
To configure the handshake after placing the mods, we must run the server once to generate the configuration structure, then shut it down to inject the secret.&lt;br /&gt;
Update start.sh to point to fabric-server-launch.jar instead of server.jar&lt;br /&gt;
 sed -i &#039;s/server.jar/fabric-server-launch.jar/&#039; start.sh&lt;br /&gt;
Initial run to generate config (Type &#039;stop&#039; once the &#039;Done&#039; message appears)&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now, we create the configuration file and link it to Vangueria. This is where we ensure the backend only trusts traffic coming from our proxy.&lt;br /&gt;
 mkdir -p ~/minecraft_server/config&lt;br /&gt;
 nano ~/minecraft_server/config/FabricProxy-Lite.toml&lt;br /&gt;
Paste the following configuration into the file, ensuring the secret matches the one obtained from Vangueria:&lt;br /&gt;
 enabled = true&lt;br /&gt;
 hackOnlineMode = true&lt;br /&gt;
 secret = &amp;quot;PASTE_YOUR_VANGUERIA_SECRET_HERE&amp;quot;&lt;br /&gt;
The final step is to adjust the server.properties file. Because Vangueria handles the official Mojang authentication at the &amp;quot;front door,&amp;quot; the backend server must be set to offline mode to allow the proxy to pass the authenticated user data through.&lt;br /&gt;
 sed -i &#039;s/online-mode=true/online-mode=false/&#039; server.properties&lt;br /&gt;
With the configuration complete, the server should be launched inside a named screen session to ensure it remains active.&lt;br /&gt;
 screen -S minecraft ./start.sh&lt;br /&gt;
We should now change the Pfsense port forward rule to forward traffic to the 192.168.100.29 (IP address of Vangueria) and then connecting a client from a laptop outside of Pfsense and using the address cherry.seaoffate.net, we can try using the IP address of the Pfsense WAN port but it may not work (if the default server is set to cherry it may connect)&lt;br /&gt;
&lt;br /&gt;
===Additional Options===&lt;br /&gt;
&lt;br /&gt;
There are a few additional considerations that will make the servers run more reliably. The first is thing that needs to be done is to run the server in a screen so that there does not need to be a SSH session to be running. The following will start a screen called minecraft and will execute the start.sh command. &lt;br /&gt;
 screen -S minecraft ./start&lt;br /&gt;
To exit the minecraft screen and return to the main SSH type ctrl + a and then d, the minecraft screen can be reloaded with the command &lt;br /&gt;
 screen -r minecraft&lt;br /&gt;
The next thing that we will need to do is to have the minecraft server start whenever the host reboots. So we need to add a cron tab to the start.sh&lt;br /&gt;
 crontab -e&lt;br /&gt;
Select nano if asked then add the line &lt;br /&gt;
 @reboot screen -dmS minecraft /home/nigel/minecraft_server/start.sh&lt;br /&gt;
&lt;br /&gt;
The next thing is not a minecraft helper exactly but it will be useful as a reminder in the future. When a user logs on to the host the message of the day will be displayed to add simple notes to the message we can simply edit the motd with the command&lt;br /&gt;
 sudo nano /etc/motd&lt;br /&gt;
&lt;br /&gt;
===Adding a second Minecraft server Apple===&lt;br /&gt;
&lt;br /&gt;
Now that we have the basic setup with potential for multiple hosts we will need to create at least one more so that we can prove the proxy works as intended. The next server will be a different version with some mods. As soon as we start adding mods to a Minecraft world they will use more resources so we will need the next host to be a bit better specified.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 5 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 12GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 150GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Apple||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.35 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
&lt;br /&gt;
As we did with the cherry host earlier we need to configure the hardware changes that have been made on the basic specification like adding the Lexar HD as the swap file. We must stop using the swap partition on the primary drive so we can move it out of the way. Turn off all swap.&lt;br /&gt;
 sudo swapoff -a&lt;br /&gt;
Since your swap partition (sda3) is at the end of the disk, it acts as a &amp;quot;blocker.&amp;quot; We need to delete it and the root partition, then recreate the root partition to fill the entire space.&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
* Type p to print the table (confirming sda2 is root and sda3 is swap).&lt;br /&gt;
* Type d then 3 to delete the swap partition.&lt;br /&gt;
* Type d then 2 to delete the root partition (Don&#039;t worry, the data stays in the blocks).&lt;br /&gt;
* Step B: Recreate and Expand&lt;br /&gt;
* Type n for a new partition.&lt;br /&gt;
* Type p for Primary. Note if disk is using a GPT (GUID Partition Table) there will be no P option, primary partitions only exist in the old MBR style of disks&lt;br /&gt;
* Type 2 for Partition number 2.&lt;br /&gt;
* Press Enter for the default Start Sector (it must match the old start sector of sda2).&lt;br /&gt;
* Press Enter for the default End Sector (this will now jump to the end of the 150GB disk).&lt;br /&gt;
* CRITICAL: When it asks &amp;quot;Do you want to remove the signature?&amp;quot;, type N.&lt;br /&gt;
* Type w to write changes and exit.&lt;br /&gt;
Now, reboot to make sure the kernel is looking at the new 150GB table entry.&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
Once you log back in, expand the actual data &amp;quot;container&amp;quot; (the ext4 filesystem) to fill that new partition:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
Now that the main drive is expanded, let&#039;s get that high-speed swap set up on your 16GB secondary disk.&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
We need to update /etc/fstab so your VM knows where to find its memory &amp;quot;safety net&amp;quot; on every boot.&lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Look for the line that mentions the old swap (it likely mentions sda3 or a long UUID string). Delete that line or put a # at the start of it. Add this new line at the bottom:&lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
Save and exit. Then to confirm the changes have been made use the following commands to show the new sda2 disk size and the swap disk&lt;br /&gt;
 df -h&lt;br /&gt;
 free -h&lt;br /&gt;
&lt;br /&gt;
====Software installation====&lt;br /&gt;
&lt;br /&gt;
Since Apple is a fresh VM, we need to ensure the underlying Debian OS is fully patched and has the necessary build tools and repositories before we drop a massive modpack into it. Modern modpacks like FTB University rely heavily on Java 21 or Java 25, so we will set that foundation now. First, we refresh the local package index and upgrade any existing system components. Update package lists and upgrade system and install essential utilities for file management and monitoring&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
 sudo apt install -y htop screen wget curl jq unzip zip&lt;br /&gt;
Install Java 25 and verify the version to ensure it&#039;s active&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless&lt;br /&gt;
 java -version&lt;br /&gt;
with the JRE installed we can now pull the explicit API endpoint for the FTB University installer. We will use the -JLO flags with curl. This tells it to follow redirections, process headers properly, and save the binary with its true system filename so the metadata doesn&#039;t drop.&lt;br /&gt;
 mkdir ~/ftb_university&lt;br /&gt;
 cd ~/ftb_university&lt;br /&gt;
 curl -JLO &amp;quot;https://api.feed-the-beast.com/v1/modpacks/public/modpack/108/latest/server/linux&amp;quot;&lt;br /&gt;
When the file finirm ~/ftb_university/serverinstall_108_*shes downloading, it will have a specific auto-generated string name based on the pack ID. Let&#039;s make it executable and kick off the automated build process&lt;br /&gt;
 chmod +x serverinstall_108_*&lt;br /&gt;
 ./serverinstall_108_* --auto&lt;br /&gt;
Assuming the automated build script successfully assembled the library trees, we can clear the raw installation binaries to save block space. &lt;br /&gt;
  rm ~/ftb_university/serverinstall_108_*&lt;br /&gt;
We need to generate the basic runtime parameters so the engine treats your backend initialization correctly. We need accept the core EULA agreement before the server can start and Disable Mojang online lookup to yield authentication control to Vangueria.&lt;br /&gt;
 echo &amp;quot;eula=true&amp;quot; &amp;gt; ~/ftb_university/eula.txt&lt;br /&gt;
 printf &amp;quot;online-mode=false\nmotd=FTB University Home\nallow-flight=true\nmax-tick-time=180000&amp;quot; &amp;gt; ~/ftb_university/server.properties&lt;br /&gt;
We will launch the first server loop. Forge will map out the dimensions and establish the baseline mod settings.&lt;br /&gt;
 ./run.sh&lt;br /&gt;
Since this is a clean workspace, the installer script will start downloading the specific runtime libraries. Watch the console scroll past the mod registry logs. Let the text settle completely until it opens up the standard interactive game prompt (&amp;gt;). Once you see that prompt, type stop and hit Enter to close down the thread cleanly. This will finalize our asset paths so we can secure the proxy sync.&lt;br /&gt;
&lt;br /&gt;
We tried various download locations to obtain the Bungee Guard jars including Modrinth and github but they could not be located. We pulled the JAR directly from Lucko&#039;s official continuous integration server mirror. This bypassed both GitHub and Modrinth APIs completely and delivers the raw bytecode directly.&lt;br /&gt;
 curl -L -o ~/ftb_university/mods/BungeeGuard-Forge.jar &amp;quot;https://ci.lucko.me/job/BungeeGuard/lastSuccessfulBuild/artifact/forge/build/libs/BungeeGuard-Forge.jar&amp;quot;&lt;br /&gt;
 ls -lh ~/ftb_university/mods/BungeeGuard-Forge.jar&lt;br /&gt;
The jar should be several tens of kb, if it is only a few hundred bytes or less it is likely just a redirect and only the text of the redirect or some JSON text.&lt;br /&gt;
Assuming the file downloaded we match up the backend with our proxy on .&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1545</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1545"/>
		<updated>2026-05-13T08:21:45Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Software installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
The first Minecraft host needs to have enough resources to run the JVM and the server but as it just a vanilla server the specification does not need to be excessive. The table shows the highlights.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;br /&gt;
&lt;br /&gt;
===Velocity Installation===&lt;br /&gt;
&lt;br /&gt;
The Velocity server VM does not need to be especially high because all it needs to do is accept connections and forward them on to the relevant host and any associated functions like handle logon, bans and etc. Unlike the cherry host that we just setup the base specification from the Debian template needs to be cut down a bit and does not need a extra swap file or anything special.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 1 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 1GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Storage || 32GB ||  &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Vangueria ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.29 ||&lt;br /&gt;
|}&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
As there is no additions to the VM&#039;s specification there is no hardware to configure so we can get straight to the software installation. So the well known update/upgrade and the packages can be installed with&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless htop screen wget jq curl&lt;br /&gt;
Once the dependencies are installed, we create a dedicated application directory and use an automated script to identify the most recent build of Velocity 3.4.0. This ensures we are not relying on hardcoded links that may expire.&lt;br /&gt;
 mkdir ~/velocity &amp;amp;&amp;amp; cd ~/velocity&lt;br /&gt;
 export PROJECT=&amp;quot;velocity&amp;quot;&lt;br /&gt;
 export VERSION=&amp;quot;3.4.0-SNAPSHOT&amp;quot;&lt;br /&gt;
 export LATEST_BUILD=$(curl -s https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION} | jq &#039;.builds[-1]&#039;)&lt;br /&gt;
 wget -O ~/velocity/velocity.jar &amp;quot;https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION}/builds/${LATEST_BUILD}/downloads/${PROJECT}-${VERSION}-${LATEST_BUILD}.jar&amp;quot;&lt;br /&gt;
The initial boot of Velocity is performed to generate the necessary configuration files. We launch it with a 512MB heap size and then shut it down gracefully using the end command once the prompt appears.&lt;br /&gt;
 java -Xms512M -Xmx512M -jar velocity.jar&lt;br /&gt;
&lt;br /&gt;
====Proxy Configuration and Routing====&lt;br /&gt;
&lt;br /&gt;
The primary configuration for the proxy is handled within the velocity.toml file. This file dictates how the proxy listens for incoming traffic and how it maps domain names to internal IP addresses. We edit this file to ensure the proxy is listening on all interfaces and that it is using the modern forwarding protocol.&lt;br /&gt;
 nano ~/velocity/velocity.toml&lt;br /&gt;
Modify these specific lines:&lt;br /&gt;
* Bind Address: bind = &amp;quot;0.0.0.0:25565&amp;quot; (Allows it to hear traffic from pfSense).&lt;br /&gt;
* Forwarding Mode: player-info-forwarding-mode = &amp;quot;modern&amp;quot; (This is the most secure protocol for 2026).&lt;br /&gt;
* ping-passthrough should be set to ALL. This is to ensure the server list on the Minecraft client correctly displays the status and version of the backend servers&lt;br /&gt;
* Server List: Scroll down to the [servers] section:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[servers]&lt;br /&gt;
 cherry = &amp;quot;192.168.100.30:25565&amp;quot;&lt;br /&gt;
 apple = &amp;quot;192.168.100.35:25565&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 [servers]&lt;br /&gt;
 try = [&lt;br /&gt;
    &amp;quot;cherry&amp;quot;&lt;br /&gt;
 ]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Forced Hosts: This tells the proxy which server to pick based on the URL the player typed:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[forced-hosts]&lt;br /&gt;
 &amp;quot;cherry.seaoffate.net&amp;quot; = [&amp;quot;cherry&amp;quot;]&lt;br /&gt;
 &amp;quot;apple.seaoffate.net&amp;quot; = [&amp;quot;apple&amp;quot;]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Save and close the file. next we need a start.sh file for Velocity &lt;br /&gt;
 nano ~/velocity/start.sh&lt;br /&gt;
copy the following into the file&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Vangueria Proxy ---&amp;quot;&lt;br /&gt;
     java -Xms512M -Xmx512M \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar velocity.jar&lt;br /&gt;
     echo &amp;quot;--- Proxy stopped. Restarting in 5s ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
To make the script executable &lt;br /&gt;
 chmod +x ~/velocity/start.sh&lt;br /&gt;
At this point the since Vangueria is now set to Modern Forwarding, Cherry will reject all connections until it has the forwarding.secret. the secret can be obtained with the command&lt;br /&gt;
 cat ~/velocity/forwarding.secret&lt;br /&gt;
Copy the code to a safe location because we will need it to setup cherry (and apple). then we should be able to finally start the proxy with the start.sh&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now we move to cherry to setup it&#039;s ability to receive connections from Vangueria. &lt;br /&gt;
&lt;br /&gt;
====Configuring Cherry To Accept Proxied Connections====&lt;br /&gt;
&lt;br /&gt;
To complete the integration between the proxy and the backend, Cherry must be transitioned from a standalone Vanilla server to a &amp;quot;Proxy-Aware&amp;quot; host. Because Vanilla Minecraft does not natively support Velocity’s Modern Forwarding (the security handshake), we use the Fabric Loader as a lightweight wrapper. This allows us to install a bridge mod that validates the secret key without changing the gameplay experience.The transition of Cherry involves three main phases: installing the Fabric environment, adding the bridge mods, and configuring the security handshake to match Vangueria.&lt;br /&gt;
&lt;br /&gt;
First, we must stop the existing server and install the Fabric transition layer. This replaces the standard Mojang launcher with a version capable of loading the security bridge. We need to download the Fabric Installer and then Install Fabric for the 1.21.1 environment.&lt;br /&gt;
 cd ~/minecraft_server&lt;br /&gt;
 wget https://maven.fabricmc.net/net/fabricmc/fabric-installer/1.0.1/fabric-installer-1.0.1.jar&lt;br /&gt;
 java -jar fabric-installer-1.0.1.jar server -mcversion 1.21.1 -downloadMinecraft&lt;br /&gt;
Once complete, the installer will have created a new file named fabric-server-launch.jar. This is now the primary entry point for the server.&lt;br /&gt;
&lt;br /&gt;
To install the Security Bridge we require two specific components in the mods folder: the Fabric API (the library that allows mods to interact with the game engine) and FabricProxy-Lite (the specific mod that handles the Velocity secret key). It is vital to use version-matched JARs for 1.21.1 to ensure stability.&lt;br /&gt;
 mkdir -p ~/minecraft_server/mods&lt;br /&gt;
 wget -O ~/minecraft_server/mods/FabricProxy-Lite.jar https://github.com/OKTW-Network/FabricProxy-Lite/releases/download/v2.10.1/FabricProxy-Lite-2.10.1.jar&lt;br /&gt;
 wget -O ~/minecraft_server/mods/fabric-api.jar https://github.com/FabricMC/fabric-api/releases/download/0.116.11%2B1.21.1/fabric-api-0.116.11+1.21.1.jar&lt;br /&gt;
&lt;br /&gt;
To configure the handshake after placing the mods, we must run the server once to generate the configuration structure, then shut it down to inject the secret.&lt;br /&gt;
Update start.sh to point to fabric-server-launch.jar instead of server.jar&lt;br /&gt;
 sed -i &#039;s/server.jar/fabric-server-launch.jar/&#039; start.sh&lt;br /&gt;
Initial run to generate config (Type &#039;stop&#039; once the &#039;Done&#039; message appears)&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now, we create the configuration file and link it to Vangueria. This is where we ensure the backend only trusts traffic coming from our proxy.&lt;br /&gt;
 mkdir -p ~/minecraft_server/config&lt;br /&gt;
 nano ~/minecraft_server/config/FabricProxy-Lite.toml&lt;br /&gt;
Paste the following configuration into the file, ensuring the secret matches the one obtained from Vangueria:&lt;br /&gt;
 enabled = true&lt;br /&gt;
 hackOnlineMode = true&lt;br /&gt;
 secret = &amp;quot;PASTE_YOUR_VANGUERIA_SECRET_HERE&amp;quot;&lt;br /&gt;
The final step is to adjust the server.properties file. Because Vangueria handles the official Mojang authentication at the &amp;quot;front door,&amp;quot; the backend server must be set to offline mode to allow the proxy to pass the authenticated user data through.&lt;br /&gt;
 sed -i &#039;s/online-mode=true/online-mode=false/&#039; server.properties&lt;br /&gt;
With the configuration complete, the server should be launched inside a named screen session to ensure it remains active.&lt;br /&gt;
 screen -S minecraft ./start.sh&lt;br /&gt;
We should now change the Pfsense port forward rule to forward traffic to the 192.168.100.29 (IP address of Vangueria) and then connecting a client from a laptop outside of Pfsense and using the address cherry.seaoffate.net, we can try using the IP address of the Pfsense WAN port but it may not work (if the default server is set to cherry it may connect)&lt;br /&gt;
&lt;br /&gt;
===Additional Options===&lt;br /&gt;
&lt;br /&gt;
There are a few additional considerations that will make the servers run more reliably. The first is thing that needs to be done is to run the server in a screen so that there does not need to be a SSH session to be running. The following will start a screen called minecraft and will execute the start.sh command. &lt;br /&gt;
 screen -S minecraft ./start&lt;br /&gt;
To exit the minecraft screen and return to the main SSH type ctrl + a and then d, the minecraft screen can be reloaded with the command &lt;br /&gt;
 screen -r minecraft&lt;br /&gt;
The next thing that we will need to do is to have the minecraft server start whenever the host reboots. So we need to add a cron tab to the start.sh&lt;br /&gt;
 crontab -e&lt;br /&gt;
Select nano if asked then add the line &lt;br /&gt;
 @reboot screen -dmS minecraft /home/nigel/minecraft_server/start.sh&lt;br /&gt;
&lt;br /&gt;
The next thing is not a minecraft helper exactly but it will be useful as a reminder in the future. When a user logs on to the host the message of the day will be displayed to add simple notes to the message we can simply edit the motd with the command&lt;br /&gt;
 sudo nano /etc/motd&lt;br /&gt;
&lt;br /&gt;
===Adding a second Minecraft server Apple===&lt;br /&gt;
&lt;br /&gt;
Now that we have the basic setup with potential for multiple hosts we will need to create at least one more so that we can prove the proxy works as intended. The next server will be a different version with some mods. As soon as we start adding mods to a Minecraft world they will use more resources so we will need the next host to be a bit better specified.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 5 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 12GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 150GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Apple||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.35 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
&lt;br /&gt;
As we did with the cherry host earlier we need to configure the hardware changes that have been made on the basic specification like adding the Lexar HD as the swap file. We must stop using the swap partition on the primary drive so we can move it out of the way. Turn off all swap.&lt;br /&gt;
 sudo swapoff -a&lt;br /&gt;
Since your swap partition (sda3) is at the end of the disk, it acts as a &amp;quot;blocker.&amp;quot; We need to delete it and the root partition, then recreate the root partition to fill the entire space.&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
* Type p to print the table (confirming sda2 is root and sda3 is swap).&lt;br /&gt;
* Type d then 3 to delete the swap partition.&lt;br /&gt;
* Type d then 2 to delete the root partition (Don&#039;t worry, the data stays in the blocks).&lt;br /&gt;
* Step B: Recreate and Expand&lt;br /&gt;
* Type n for a new partition.&lt;br /&gt;
* Type p for Primary. Note if disk is using a GPT (GUID Partition Table) there will be no P option, primary partitions only exist in the old MBR style of disks&lt;br /&gt;
* Type 2 for Partition number 2.&lt;br /&gt;
* Press Enter for the default Start Sector (it must match the old start sector of sda2).&lt;br /&gt;
* Press Enter for the default End Sector (this will now jump to the end of the 150GB disk).&lt;br /&gt;
* CRITICAL: When it asks &amp;quot;Do you want to remove the signature?&amp;quot;, type N.&lt;br /&gt;
* Type w to write changes and exit.&lt;br /&gt;
Now, reboot to make sure the kernel is looking at the new 150GB table entry.&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
Once you log back in, expand the actual data &amp;quot;container&amp;quot; (the ext4 filesystem) to fill that new partition:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
Now that the main drive is expanded, let&#039;s get that high-speed swap set up on your 16GB secondary disk.&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
We need to update /etc/fstab so your VM knows where to find its memory &amp;quot;safety net&amp;quot; on every boot.&lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Look for the line that mentions the old swap (it likely mentions sda3 or a long UUID string). Delete that line or put a # at the start of it. Add this new line at the bottom:&lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
Save and exit. Then to confirm the changes have been made use the following commands to show the new sda2 disk size and the swap disk&lt;br /&gt;
 df -h&lt;br /&gt;
 free -h&lt;br /&gt;
&lt;br /&gt;
====Software installation====&lt;br /&gt;
&lt;br /&gt;
Since Apple is a fresh VM, we need to ensure the underlying Debian OS is fully patched and has the necessary build tools and repositories before we drop a massive modpack into it. Modern modpacks like ATM10 (Minecraft 1.21.1) rely heavily on Java 21 or Java 25, so we will set that foundation now. First, we refresh the local package index and upgrade any existing system components. Update package lists and upgrade system and install essential utilities for file management and monitoring&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
 sudo apt install -y htop screen wget curl jq unzip zip&lt;br /&gt;
Install Java 25 and verify the version to ensure it&#039;s active&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless&lt;br /&gt;
 java -version&lt;br /&gt;
Now that the system is ready, we can create the home for Apple. Create the Modpack Directory&lt;br /&gt;
 mkdir ~/atm_server &amp;amp;&amp;amp; cd ~/atm_server&lt;br /&gt;
We now need the server file ServerFiles-6.6.zip but it would appear that the curseforge website don&#039;t allow wget downloads so the best way to get the file is to download via http and scp it to the atm-server directory. When the .zip file is in the atm directory we unzip it&lt;br /&gt;
 unzip ServerFiles-6.6.zip&lt;br /&gt;
Make the installer executable&lt;br /&gt;
 chmod +x startserver.sh&lt;br /&gt;
Run the installer&lt;br /&gt;
 ./startserver.sh&lt;br /&gt;
Wait for completion: This will download the NeoForge runtime libraries. Once it finishes, it will usually create a run.sh or simply exit back to the prompt after preparing the environment. Immediately after it finishes, we need to apply the &amp;quot;tried and tested&amp;quot; security and performance settings. Note that it may have to be stopped and then do a ctrl + c to close it completely so we can accept the eula.&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
The final Steps to get Apple Online now that you have accepted the EULA, follow these final steps to link it to Vangueria and give it the power it needs.&lt;br /&gt;
&lt;br /&gt;
Set the Memory (Critical for ATM10)&lt;br /&gt;
If you don&#039;t do this, the server will try to run on 2GB or 4GB and will crash during world generation.&lt;br /&gt;
 nano ~/atm_server/user_jvm_args.txt&lt;br /&gt;
Find the memory lines and change them to 10G (leaving 2GB for Debian):&lt;br /&gt;
 -Xms10G&lt;br /&gt;
 -Xmx10G&lt;br /&gt;
Save and exit. Since we have already unzipped the files, the bridge mod is already in the mods folder, but we need to give Apple the &amp;quot;password&amp;quot; to trust Vangueria. Create the secret file and paste your Vangueria secret string&lt;br /&gt;
 nano ~/atm_server/forwarding.secret&lt;br /&gt;
Save and close. Next we disable Online Mode&lt;br /&gt;
 sed -i &#039;s/online-mode=true/online-mode=false/&#039; ~/atm_server/server.properties&lt;br /&gt;
We are now ready to launch the Beast. Start it in a named screen. Be patient: ATM10 will take 5 to 10 minutes to boot the first time while it processes those ~500 mods.&lt;br /&gt;
 screen -S apple ./startserver.sh&lt;br /&gt;
to prove that it works we will have connect a client. The goo news is that there should be no extra configuration to manage because the traffic is just being redirected from Vangueria like cherry.&lt;br /&gt;
&lt;br /&gt;
To keep the Apple server automated and robust, you need a string that launches a detached screen session immediately upon the VM booting up. On the Apple VM, run:&lt;br /&gt;
 crontab -e&lt;br /&gt;
Scroll to the very bottom of the file and paste this exact string:&lt;br /&gt;
 @reboot screen -dmS apple /home/nigel/atm_server/startserver.sh&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1544</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1544"/>
		<updated>2026-05-12T22:37:35Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Software installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
The first Minecraft host needs to have enough resources to run the JVM and the server but as it just a vanilla server the specification does not need to be excessive. The table shows the highlights.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;br /&gt;
&lt;br /&gt;
===Velocity Installation===&lt;br /&gt;
&lt;br /&gt;
The Velocity server VM does not need to be especially high because all it needs to do is accept connections and forward them on to the relevant host and any associated functions like handle logon, bans and etc. Unlike the cherry host that we just setup the base specification from the Debian template needs to be cut down a bit and does not need a extra swap file or anything special.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 1 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 1GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Storage || 32GB ||  &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Vangueria ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.29 ||&lt;br /&gt;
|}&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
As there is no additions to the VM&#039;s specification there is no hardware to configure so we can get straight to the software installation. So the well known update/upgrade and the packages can be installed with&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless htop screen wget jq curl&lt;br /&gt;
Once the dependencies are installed, we create a dedicated application directory and use an automated script to identify the most recent build of Velocity 3.4.0. This ensures we are not relying on hardcoded links that may expire.&lt;br /&gt;
 mkdir ~/velocity &amp;amp;&amp;amp; cd ~/velocity&lt;br /&gt;
 export PROJECT=&amp;quot;velocity&amp;quot;&lt;br /&gt;
 export VERSION=&amp;quot;3.4.0-SNAPSHOT&amp;quot;&lt;br /&gt;
 export LATEST_BUILD=$(curl -s https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION} | jq &#039;.builds[-1]&#039;)&lt;br /&gt;
 wget -O ~/velocity/velocity.jar &amp;quot;https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION}/builds/${LATEST_BUILD}/downloads/${PROJECT}-${VERSION}-${LATEST_BUILD}.jar&amp;quot;&lt;br /&gt;
The initial boot of Velocity is performed to generate the necessary configuration files. We launch it with a 512MB heap size and then shut it down gracefully using the end command once the prompt appears.&lt;br /&gt;
 java -Xms512M -Xmx512M -jar velocity.jar&lt;br /&gt;
&lt;br /&gt;
====Proxy Configuration and Routing====&lt;br /&gt;
&lt;br /&gt;
The primary configuration for the proxy is handled within the velocity.toml file. This file dictates how the proxy listens for incoming traffic and how it maps domain names to internal IP addresses. We edit this file to ensure the proxy is listening on all interfaces and that it is using the modern forwarding protocol.&lt;br /&gt;
 nano ~/velocity/velocity.toml&lt;br /&gt;
Modify these specific lines:&lt;br /&gt;
* Bind Address: bind = &amp;quot;0.0.0.0:25565&amp;quot; (Allows it to hear traffic from pfSense).&lt;br /&gt;
* Forwarding Mode: player-info-forwarding-mode = &amp;quot;modern&amp;quot; (This is the most secure protocol for 2026).&lt;br /&gt;
* ping-passthrough should be set to ALL. This is to ensure the server list on the Minecraft client correctly displays the status and version of the backend servers&lt;br /&gt;
* Server List: Scroll down to the [servers] section:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[servers]&lt;br /&gt;
 cherry = &amp;quot;192.168.100.30:25565&amp;quot;&lt;br /&gt;
 apple = &amp;quot;192.168.100.35:25565&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 [servers]&lt;br /&gt;
 try = [&lt;br /&gt;
    &amp;quot;cherry&amp;quot;&lt;br /&gt;
 ]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Forced Hosts: This tells the proxy which server to pick based on the URL the player typed:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[forced-hosts]&lt;br /&gt;
 &amp;quot;cherry.seaoffate.net&amp;quot; = [&amp;quot;cherry&amp;quot;]&lt;br /&gt;
 &amp;quot;apple.seaoffate.net&amp;quot; = [&amp;quot;apple&amp;quot;]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Save and close the file. next we need a start.sh file for Velocity &lt;br /&gt;
 nano ~/velocity/start.sh&lt;br /&gt;
copy the following into the file&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Vangueria Proxy ---&amp;quot;&lt;br /&gt;
     java -Xms512M -Xmx512M \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar velocity.jar&lt;br /&gt;
     echo &amp;quot;--- Proxy stopped. Restarting in 5s ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
To make the script executable &lt;br /&gt;
 chmod +x ~/velocity/start.sh&lt;br /&gt;
At this point the since Vangueria is now set to Modern Forwarding, Cherry will reject all connections until it has the forwarding.secret. the secret can be obtained with the command&lt;br /&gt;
 cat ~/velocity/forwarding.secret&lt;br /&gt;
Copy the code to a safe location because we will need it to setup cherry (and apple). then we should be able to finally start the proxy with the start.sh&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now we move to cherry to setup it&#039;s ability to receive connections from Vangueria. &lt;br /&gt;
&lt;br /&gt;
====Configuring Cherry To Accept Proxied Connections====&lt;br /&gt;
&lt;br /&gt;
To complete the integration between the proxy and the backend, Cherry must be transitioned from a standalone Vanilla server to a &amp;quot;Proxy-Aware&amp;quot; host. Because Vanilla Minecraft does not natively support Velocity’s Modern Forwarding (the security handshake), we use the Fabric Loader as a lightweight wrapper. This allows us to install a bridge mod that validates the secret key without changing the gameplay experience.The transition of Cherry involves three main phases: installing the Fabric environment, adding the bridge mods, and configuring the security handshake to match Vangueria.&lt;br /&gt;
&lt;br /&gt;
First, we must stop the existing server and install the Fabric transition layer. This replaces the standard Mojang launcher with a version capable of loading the security bridge. We need to download the Fabric Installer and then Install Fabric for the 1.21.1 environment.&lt;br /&gt;
 cd ~/minecraft_server&lt;br /&gt;
 wget https://maven.fabricmc.net/net/fabricmc/fabric-installer/1.0.1/fabric-installer-1.0.1.jar&lt;br /&gt;
 java -jar fabric-installer-1.0.1.jar server -mcversion 1.21.1 -downloadMinecraft&lt;br /&gt;
Once complete, the installer will have created a new file named fabric-server-launch.jar. This is now the primary entry point for the server.&lt;br /&gt;
&lt;br /&gt;
To install the Security Bridge we require two specific components in the mods folder: the Fabric API (the library that allows mods to interact with the game engine) and FabricProxy-Lite (the specific mod that handles the Velocity secret key). It is vital to use version-matched JARs for 1.21.1 to ensure stability.&lt;br /&gt;
 mkdir -p ~/minecraft_server/mods&lt;br /&gt;
 wget -O ~/minecraft_server/mods/FabricProxy-Lite.jar https://github.com/OKTW-Network/FabricProxy-Lite/releases/download/v2.10.1/FabricProxy-Lite-2.10.1.jar&lt;br /&gt;
 wget -O ~/minecraft_server/mods/fabric-api.jar https://github.com/FabricMC/fabric-api/releases/download/0.116.11%2B1.21.1/fabric-api-0.116.11+1.21.1.jar&lt;br /&gt;
&lt;br /&gt;
To configure the handshake after placing the mods, we must run the server once to generate the configuration structure, then shut it down to inject the secret.&lt;br /&gt;
Update start.sh to point to fabric-server-launch.jar instead of server.jar&lt;br /&gt;
 sed -i &#039;s/server.jar/fabric-server-launch.jar/&#039; start.sh&lt;br /&gt;
Initial run to generate config (Type &#039;stop&#039; once the &#039;Done&#039; message appears)&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now, we create the configuration file and link it to Vangueria. This is where we ensure the backend only trusts traffic coming from our proxy.&lt;br /&gt;
 mkdir -p ~/minecraft_server/config&lt;br /&gt;
 nano ~/minecraft_server/config/FabricProxy-Lite.toml&lt;br /&gt;
Paste the following configuration into the file, ensuring the secret matches the one obtained from Vangueria:&lt;br /&gt;
 enabled = true&lt;br /&gt;
 hackOnlineMode = true&lt;br /&gt;
 secret = &amp;quot;PASTE_YOUR_VANGUERIA_SECRET_HERE&amp;quot;&lt;br /&gt;
The final step is to adjust the server.properties file. Because Vangueria handles the official Mojang authentication at the &amp;quot;front door,&amp;quot; the backend server must be set to offline mode to allow the proxy to pass the authenticated user data through.&lt;br /&gt;
 sed -i &#039;s/online-mode=true/online-mode=false/&#039; server.properties&lt;br /&gt;
With the configuration complete, the server should be launched inside a named screen session to ensure it remains active.&lt;br /&gt;
 screen -S minecraft ./start.sh&lt;br /&gt;
We should now change the Pfsense port forward rule to forward traffic to the 192.168.100.29 (IP address of Vangueria) and then connecting a client from a laptop outside of Pfsense and using the address cherry.seaoffate.net, we can try using the IP address of the Pfsense WAN port but it may not work (if the default server is set to cherry it may connect)&lt;br /&gt;
&lt;br /&gt;
===Additional Options===&lt;br /&gt;
&lt;br /&gt;
There are a few additional considerations that will make the servers run more reliably. The first is thing that needs to be done is to run the server in a screen so that there does not need to be a SSH session to be running. The following will start a screen called minecraft and will execute the start.sh command. &lt;br /&gt;
 screen -S minecraft ./start&lt;br /&gt;
To exit the minecraft screen and return to the main SSH type ctrl + a and then d, the minecraft screen can be reloaded with the command &lt;br /&gt;
 screen -r minecraft&lt;br /&gt;
The next thing that we will need to do is to have the minecraft server start whenever the host reboots. So we need to add a cron tab to the start.sh&lt;br /&gt;
 crontab -e&lt;br /&gt;
Select nano if asked then add the line &lt;br /&gt;
 @reboot screen -dmS minecraft /home/nigel/minecraft_server/start.sh&lt;br /&gt;
&lt;br /&gt;
The next thing is not a minecraft helper exactly but it will be useful as a reminder in the future. When a user logs on to the host the message of the day will be displayed to add simple notes to the message we can simply edit the motd with the command&lt;br /&gt;
 sudo nano /etc/motd&lt;br /&gt;
&lt;br /&gt;
===Adding a second Minecraft server Apple===&lt;br /&gt;
&lt;br /&gt;
Now that we have the basic setup with potential for multiple hosts we will need to create at least one more so that we can prove the proxy works as intended. The next server will be a different version with some mods. As soon as we start adding mods to a Minecraft world they will use more resources so we will need the next host to be a bit better specified.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 5 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 12GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 150GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Apple||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.35 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
&lt;br /&gt;
As we did with the cherry host earlier we need to configure the hardware changes that have been made on the basic specification like adding the Lexar HD as the swap file. We must stop using the swap partition on the primary drive so we can move it out of the way. Turn off all swap.&lt;br /&gt;
 sudo swapoff -a&lt;br /&gt;
Since your swap partition (sda3) is at the end of the disk, it acts as a &amp;quot;blocker.&amp;quot; We need to delete it and the root partition, then recreate the root partition to fill the entire space.&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
* Type p to print the table (confirming sda2 is root and sda3 is swap).&lt;br /&gt;
* Type d then 3 to delete the swap partition.&lt;br /&gt;
* Type d then 2 to delete the root partition (Don&#039;t worry, the data stays in the blocks).&lt;br /&gt;
* Step B: Recreate and Expand&lt;br /&gt;
* Type n for a new partition.&lt;br /&gt;
* Type p for Primary. Note if disk is using a GPT (GUID Partition Table) there will be no P option, primary partitions only exist in the old MBR style of disks&lt;br /&gt;
* Type 2 for Partition number 2.&lt;br /&gt;
* Press Enter for the default Start Sector (it must match the old start sector of sda2).&lt;br /&gt;
* Press Enter for the default End Sector (this will now jump to the end of the 150GB disk).&lt;br /&gt;
* CRITICAL: When it asks &amp;quot;Do you want to remove the signature?&amp;quot;, type N.&lt;br /&gt;
* Type w to write changes and exit.&lt;br /&gt;
Now, reboot to make sure the kernel is looking at the new 150GB table entry.&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
Once you log back in, expand the actual data &amp;quot;container&amp;quot; (the ext4 filesystem) to fill that new partition:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
Now that the main drive is expanded, let&#039;s get that high-speed swap set up on your 16GB secondary disk.&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
We need to update /etc/fstab so your VM knows where to find its memory &amp;quot;safety net&amp;quot; on every boot.&lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Look for the line that mentions the old swap (it likely mentions sda3 or a long UUID string). Delete that line or put a # at the start of it. Add this new line at the bottom:&lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
Save and exit. Then to confirm the changes have been made use the following commands to show the new sda2 disk size and the swap disk&lt;br /&gt;
 df -h&lt;br /&gt;
 free -h&lt;br /&gt;
&lt;br /&gt;
====Software installation====&lt;br /&gt;
&lt;br /&gt;
Since Apple is a fresh VM, we need to ensure the underlying Debian OS is fully patched and has the necessary build tools and repositories before we drop a massive modpack into it. Modern modpacks like ATM10 (Minecraft 1.21.1) rely heavily on Java 21 or Java 25, so we will set that foundation now. First, we refresh the local package index and upgrade any existing system components. Update package lists and upgrade system and install essential utilities for file management and monitoring&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
 sudo apt install -y htop screen wget curl jq unzip zip&lt;br /&gt;
Install Java 25 and verify the version to ensure it&#039;s active&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless&lt;br /&gt;
 java -version&lt;br /&gt;
Now that the system is ready, we can create the home for Apple. Create the Modpack Directory&lt;br /&gt;
 mkdir ~/atm_server &amp;amp;&amp;amp; cd ~/atm_server&lt;br /&gt;
We now need the server file ServerFiles-6.6.zip but it would appear that the curseforge website don&#039;t allow wget downloads so the best way to get the file is to download via http and scp it to the atm-server directory. When the .zip file is in the atm directory we unzip it&lt;br /&gt;
 unzip ServerFiles-6.6.zip&lt;br /&gt;
Make the installer executable&lt;br /&gt;
 chmod +x startserver.sh&lt;br /&gt;
Run the installer&lt;br /&gt;
 ./startserver.sh&lt;br /&gt;
Wait for completion: This will download the NeoForge runtime libraries. Once it finishes, it will usually create a run.sh or simply exit back to the prompt after preparing the environment. Immediately after it finishes, we need to apply the &amp;quot;tried and tested&amp;quot; security and performance settings. Note that it may have to be stopped and then do a ctrl + c to close it completely so we can accept the eula.&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
The final Steps to get Apple Online now that you have accepted the EULA, follow these final steps to link it to Vangueria and give it the power it needs.&lt;br /&gt;
&lt;br /&gt;
Set the Memory (Critical for ATM10)&lt;br /&gt;
If you don&#039;t do this, the server will try to run on 2GB or 4GB and will crash during world generation.&lt;br /&gt;
 nano ~/atm_server/user_jvm_args.txt&lt;br /&gt;
Find the memory lines and change them to 10G (leaving 2GB for Debian):&lt;br /&gt;
 -Xms10G&lt;br /&gt;
 -Xmx10G&lt;br /&gt;
Save and exit. Since we have already unzipped the files, the bridge mod is already in the mods folder, but we need to give Apple the &amp;quot;password&amp;quot; to trust Vangueria. Create the secret file and paste your Vangueria secret string&lt;br /&gt;
 nano ~/atm_server/forwarding.secret&lt;br /&gt;
Save and close. Next we disable Online Mode&lt;br /&gt;
 sed -i &#039;s/online-mode=true/online-mode=false/&#039; ~/atm_server/server.properties&lt;br /&gt;
We are now ready to launch the Beast. Start it in a named screen. Be patient: ATM10 will take 5 to 10 minutes to boot the first time while it processes those ~500 mods.&lt;br /&gt;
 screen -S apple ./startserver.sh&lt;br /&gt;
to prove that it works we will have connect a client. The goo news is that there should be no extra configuration to manage because the traffic is just being redirected from Vangueria like cherry.&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1543</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1543"/>
		<updated>2026-05-12T21:57:33Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Adding a second Minecraft server Apple */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
The first Minecraft host needs to have enough resources to run the JVM and the server but as it just a vanilla server the specification does not need to be excessive. The table shows the highlights.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;br /&gt;
&lt;br /&gt;
===Velocity Installation===&lt;br /&gt;
&lt;br /&gt;
The Velocity server VM does not need to be especially high because all it needs to do is accept connections and forward them on to the relevant host and any associated functions like handle logon, bans and etc. Unlike the cherry host that we just setup the base specification from the Debian template needs to be cut down a bit and does not need a extra swap file or anything special.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 1 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 1GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Storage || 32GB ||  &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Vangueria ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.29 ||&lt;br /&gt;
|}&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
As there is no additions to the VM&#039;s specification there is no hardware to configure so we can get straight to the software installation. So the well known update/upgrade and the packages can be installed with&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless htop screen wget jq curl&lt;br /&gt;
Once the dependencies are installed, we create a dedicated application directory and use an automated script to identify the most recent build of Velocity 3.4.0. This ensures we are not relying on hardcoded links that may expire.&lt;br /&gt;
 mkdir ~/velocity &amp;amp;&amp;amp; cd ~/velocity&lt;br /&gt;
 export PROJECT=&amp;quot;velocity&amp;quot;&lt;br /&gt;
 export VERSION=&amp;quot;3.4.0-SNAPSHOT&amp;quot;&lt;br /&gt;
 export LATEST_BUILD=$(curl -s https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION} | jq &#039;.builds[-1]&#039;)&lt;br /&gt;
 wget -O ~/velocity/velocity.jar &amp;quot;https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION}/builds/${LATEST_BUILD}/downloads/${PROJECT}-${VERSION}-${LATEST_BUILD}.jar&amp;quot;&lt;br /&gt;
The initial boot of Velocity is performed to generate the necessary configuration files. We launch it with a 512MB heap size and then shut it down gracefully using the end command once the prompt appears.&lt;br /&gt;
 java -Xms512M -Xmx512M -jar velocity.jar&lt;br /&gt;
&lt;br /&gt;
====Proxy Configuration and Routing====&lt;br /&gt;
&lt;br /&gt;
The primary configuration for the proxy is handled within the velocity.toml file. This file dictates how the proxy listens for incoming traffic and how it maps domain names to internal IP addresses. We edit this file to ensure the proxy is listening on all interfaces and that it is using the modern forwarding protocol.&lt;br /&gt;
 nano ~/velocity/velocity.toml&lt;br /&gt;
Modify these specific lines:&lt;br /&gt;
* Bind Address: bind = &amp;quot;0.0.0.0:25565&amp;quot; (Allows it to hear traffic from pfSense).&lt;br /&gt;
* Forwarding Mode: player-info-forwarding-mode = &amp;quot;modern&amp;quot; (This is the most secure protocol for 2026).&lt;br /&gt;
* ping-passthrough should be set to ALL. This is to ensure the server list on the Minecraft client correctly displays the status and version of the backend servers&lt;br /&gt;
* Server List: Scroll down to the [servers] section:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[servers]&lt;br /&gt;
 cherry = &amp;quot;192.168.100.30:25565&amp;quot;&lt;br /&gt;
 apple = &amp;quot;192.168.100.35:25565&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 [servers]&lt;br /&gt;
 try = [&lt;br /&gt;
    &amp;quot;cherry&amp;quot;&lt;br /&gt;
 ]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Forced Hosts: This tells the proxy which server to pick based on the URL the player typed:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[forced-hosts]&lt;br /&gt;
 &amp;quot;cherry.seaoffate.net&amp;quot; = [&amp;quot;cherry&amp;quot;]&lt;br /&gt;
 &amp;quot;apple.seaoffate.net&amp;quot; = [&amp;quot;apple&amp;quot;]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Save and close the file. next we need a start.sh file for Velocity &lt;br /&gt;
 nano ~/velocity/start.sh&lt;br /&gt;
copy the following into the file&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Vangueria Proxy ---&amp;quot;&lt;br /&gt;
     java -Xms512M -Xmx512M \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar velocity.jar&lt;br /&gt;
     echo &amp;quot;--- Proxy stopped. Restarting in 5s ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
To make the script executable &lt;br /&gt;
 chmod +x ~/velocity/start.sh&lt;br /&gt;
At this point the since Vangueria is now set to Modern Forwarding, Cherry will reject all connections until it has the forwarding.secret. the secret can be obtained with the command&lt;br /&gt;
 cat ~/velocity/forwarding.secret&lt;br /&gt;
Copy the code to a safe location because we will need it to setup cherry (and apple). then we should be able to finally start the proxy with the start.sh&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now we move to cherry to setup it&#039;s ability to receive connections from Vangueria. &lt;br /&gt;
&lt;br /&gt;
====Configuring Cherry To Accept Proxied Connections====&lt;br /&gt;
&lt;br /&gt;
To complete the integration between the proxy and the backend, Cherry must be transitioned from a standalone Vanilla server to a &amp;quot;Proxy-Aware&amp;quot; host. Because Vanilla Minecraft does not natively support Velocity’s Modern Forwarding (the security handshake), we use the Fabric Loader as a lightweight wrapper. This allows us to install a bridge mod that validates the secret key without changing the gameplay experience.The transition of Cherry involves three main phases: installing the Fabric environment, adding the bridge mods, and configuring the security handshake to match Vangueria.&lt;br /&gt;
&lt;br /&gt;
First, we must stop the existing server and install the Fabric transition layer. This replaces the standard Mojang launcher with a version capable of loading the security bridge. We need to download the Fabric Installer and then Install Fabric for the 1.21.1 environment.&lt;br /&gt;
 cd ~/minecraft_server&lt;br /&gt;
 wget https://maven.fabricmc.net/net/fabricmc/fabric-installer/1.0.1/fabric-installer-1.0.1.jar&lt;br /&gt;
 java -jar fabric-installer-1.0.1.jar server -mcversion 1.21.1 -downloadMinecraft&lt;br /&gt;
Once complete, the installer will have created a new file named fabric-server-launch.jar. This is now the primary entry point for the server.&lt;br /&gt;
&lt;br /&gt;
To install the Security Bridge we require two specific components in the mods folder: the Fabric API (the library that allows mods to interact with the game engine) and FabricProxy-Lite (the specific mod that handles the Velocity secret key). It is vital to use version-matched JARs for 1.21.1 to ensure stability.&lt;br /&gt;
 mkdir -p ~/minecraft_server/mods&lt;br /&gt;
 wget -O ~/minecraft_server/mods/FabricProxy-Lite.jar https://github.com/OKTW-Network/FabricProxy-Lite/releases/download/v2.10.1/FabricProxy-Lite-2.10.1.jar&lt;br /&gt;
 wget -O ~/minecraft_server/mods/fabric-api.jar https://github.com/FabricMC/fabric-api/releases/download/0.116.11%2B1.21.1/fabric-api-0.116.11+1.21.1.jar&lt;br /&gt;
&lt;br /&gt;
To configure the handshake after placing the mods, we must run the server once to generate the configuration structure, then shut it down to inject the secret.&lt;br /&gt;
Update start.sh to point to fabric-server-launch.jar instead of server.jar&lt;br /&gt;
 sed -i &#039;s/server.jar/fabric-server-launch.jar/&#039; start.sh&lt;br /&gt;
Initial run to generate config (Type &#039;stop&#039; once the &#039;Done&#039; message appears)&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now, we create the configuration file and link it to Vangueria. This is where we ensure the backend only trusts traffic coming from our proxy.&lt;br /&gt;
 mkdir -p ~/minecraft_server/config&lt;br /&gt;
 nano ~/minecraft_server/config/FabricProxy-Lite.toml&lt;br /&gt;
Paste the following configuration into the file, ensuring the secret matches the one obtained from Vangueria:&lt;br /&gt;
 enabled = true&lt;br /&gt;
 hackOnlineMode = true&lt;br /&gt;
 secret = &amp;quot;PASTE_YOUR_VANGUERIA_SECRET_HERE&amp;quot;&lt;br /&gt;
The final step is to adjust the server.properties file. Because Vangueria handles the official Mojang authentication at the &amp;quot;front door,&amp;quot; the backend server must be set to offline mode to allow the proxy to pass the authenticated user data through.&lt;br /&gt;
 sed -i &#039;s/online-mode=true/online-mode=false/&#039; server.properties&lt;br /&gt;
With the configuration complete, the server should be launched inside a named screen session to ensure it remains active.&lt;br /&gt;
 screen -S minecraft ./start.sh&lt;br /&gt;
We should now change the Pfsense port forward rule to forward traffic to the 192.168.100.29 (IP address of Vangueria) and then connecting a client from a laptop outside of Pfsense and using the address cherry.seaoffate.net, we can try using the IP address of the Pfsense WAN port but it may not work (if the default server is set to cherry it may connect)&lt;br /&gt;
&lt;br /&gt;
===Additional Options===&lt;br /&gt;
&lt;br /&gt;
There are a few additional considerations that will make the servers run more reliably. The first is thing that needs to be done is to run the server in a screen so that there does not need to be a SSH session to be running. The following will start a screen called minecraft and will execute the start.sh command. &lt;br /&gt;
 screen -S minecraft ./start&lt;br /&gt;
To exit the minecraft screen and return to the main SSH type ctrl + a and then d, the minecraft screen can be reloaded with the command &lt;br /&gt;
 screen -r minecraft&lt;br /&gt;
The next thing that we will need to do is to have the minecraft server start whenever the host reboots. So we need to add a cron tab to the start.sh&lt;br /&gt;
 crontab -e&lt;br /&gt;
Select nano if asked then add the line &lt;br /&gt;
 @reboot screen -dmS minecraft /home/nigel/minecraft_server/start.sh&lt;br /&gt;
&lt;br /&gt;
The next thing is not a minecraft helper exactly but it will be useful as a reminder in the future. When a user logs on to the host the message of the day will be displayed to add simple notes to the message we can simply edit the motd with the command&lt;br /&gt;
 sudo nano /etc/motd&lt;br /&gt;
&lt;br /&gt;
===Adding a second Minecraft server Apple===&lt;br /&gt;
&lt;br /&gt;
Now that we have the basic setup with potential for multiple hosts we will need to create at least one more so that we can prove the proxy works as intended. The next server will be a different version with some mods. As soon as we start adding mods to a Minecraft world they will use more resources so we will need the next host to be a bit better specified.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 5 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 12GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 150GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Apple||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.35 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
&lt;br /&gt;
As we did with the cherry host earlier we need to configure the hardware changes that have been made on the basic specification like adding the Lexar HD as the swap file. We must stop using the swap partition on the primary drive so we can move it out of the way. Turn off all swap.&lt;br /&gt;
 sudo swapoff -a&lt;br /&gt;
Since your swap partition (sda3) is at the end of the disk, it acts as a &amp;quot;blocker.&amp;quot; We need to delete it and the root partition, then recreate the root partition to fill the entire space.&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
* Type p to print the table (confirming sda2 is root and sda3 is swap).&lt;br /&gt;
* Type d then 3 to delete the swap partition.&lt;br /&gt;
* Type d then 2 to delete the root partition (Don&#039;t worry, the data stays in the blocks).&lt;br /&gt;
* Step B: Recreate and Expand&lt;br /&gt;
* Type n for a new partition.&lt;br /&gt;
* Type p for Primary. Note if disk is using a GPT (GUID Partition Table) there will be no P option, primary partitions only exist in the old MBR style of disks&lt;br /&gt;
* Type 2 for Partition number 2.&lt;br /&gt;
* Press Enter for the default Start Sector (it must match the old start sector of sda2).&lt;br /&gt;
* Press Enter for the default End Sector (this will now jump to the end of the 150GB disk).&lt;br /&gt;
* CRITICAL: When it asks &amp;quot;Do you want to remove the signature?&amp;quot;, type N.&lt;br /&gt;
* Type w to write changes and exit.&lt;br /&gt;
Now, reboot to make sure the kernel is looking at the new 150GB table entry.&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
Once you log back in, expand the actual data &amp;quot;container&amp;quot; (the ext4 filesystem) to fill that new partition:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
Now that the main drive is expanded, let&#039;s get that high-speed swap set up on your 16GB secondary disk.&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
We need to update /etc/fstab so your VM knows where to find its memory &amp;quot;safety net&amp;quot; on every boot.&lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Look for the line that mentions the old swap (it likely mentions sda3 or a long UUID string). Delete that line or put a # at the start of it. Add this new line at the bottom:&lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
Save and exit. Then to confirm the changes have been made use the following commands to show the new sda2 disk size and the swap disk&lt;br /&gt;
 df -h&lt;br /&gt;
 free -h&lt;br /&gt;
&lt;br /&gt;
====Software installation====&lt;br /&gt;
&lt;br /&gt;
Since Apple is a fresh VM, we need to ensure the underlying Debian OS is fully patched and has the necessary build tools and repositories before we drop a massive modpack into it. Modern modpacks like ATM10 (Minecraft 1.21.1) rely heavily on Java 21 or Java 25, so we will set that foundation now. First, we refresh the local package index and upgrade any existing system components. Update package lists and upgrade system and install essential utilities for file management and monitoring&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
 sudo apt install -y htop screen wget curl jq unzip zip&lt;br /&gt;
Install Java 25 and verify the version to ensure it&#039;s active&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless&lt;br /&gt;
 java -version&lt;br /&gt;
Now that the system is ready, we can create the home for Apple. Create the Modpack Directory&lt;br /&gt;
 mkdir ~/atm_server &amp;amp;&amp;amp; cd ~/atm_server&lt;br /&gt;
We now need the server file ServerFiles-6.6.zip but it would appear that the curseforge website don&#039;t allow wget downloads so the best way to get the file is to download via http and scp it to the atm-server directory. When the .zip file is in the atm directory we unzip it&lt;br /&gt;
 unzip ServerFiles-6.6.zip&lt;br /&gt;
Make the installer executable&lt;br /&gt;
 chmod +x startserver.sh&lt;br /&gt;
Run the installer&lt;br /&gt;
 ./startserver.sh&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1542</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1542"/>
		<updated>2026-05-12T21:57:06Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Software installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
The first Minecraft host needs to have enough resources to run the JVM and the server but as it just a vanilla server the specification does not need to be excessive. The table shows the highlights.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;br /&gt;
&lt;br /&gt;
===Velocity Installation===&lt;br /&gt;
&lt;br /&gt;
The Velocity server VM does not need to be especially high because all it needs to do is accept connections and forward them on to the relevant host and any associated functions like handle logon, bans and etc. Unlike the cherry host that we just setup the base specification from the Debian template needs to be cut down a bit and does not need a extra swap file or anything special.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 1 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 1GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Storage || 32GB ||  &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Vangueria ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.29 ||&lt;br /&gt;
|}&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
As there is no additions to the VM&#039;s specification there is no hardware to configure so we can get straight to the software installation. So the well known update/upgrade and the packages can be installed with&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless htop screen wget jq curl&lt;br /&gt;
Once the dependencies are installed, we create a dedicated application directory and use an automated script to identify the most recent build of Velocity 3.4.0. This ensures we are not relying on hardcoded links that may expire.&lt;br /&gt;
 mkdir ~/velocity &amp;amp;&amp;amp; cd ~/velocity&lt;br /&gt;
 export PROJECT=&amp;quot;velocity&amp;quot;&lt;br /&gt;
 export VERSION=&amp;quot;3.4.0-SNAPSHOT&amp;quot;&lt;br /&gt;
 export LATEST_BUILD=$(curl -s https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION} | jq &#039;.builds[-1]&#039;)&lt;br /&gt;
 wget -O ~/velocity/velocity.jar &amp;quot;https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION}/builds/${LATEST_BUILD}/downloads/${PROJECT}-${VERSION}-${LATEST_BUILD}.jar&amp;quot;&lt;br /&gt;
The initial boot of Velocity is performed to generate the necessary configuration files. We launch it with a 512MB heap size and then shut it down gracefully using the end command once the prompt appears.&lt;br /&gt;
 java -Xms512M -Xmx512M -jar velocity.jar&lt;br /&gt;
&lt;br /&gt;
====Proxy Configuration and Routing====&lt;br /&gt;
&lt;br /&gt;
The primary configuration for the proxy is handled within the velocity.toml file. This file dictates how the proxy listens for incoming traffic and how it maps domain names to internal IP addresses. We edit this file to ensure the proxy is listening on all interfaces and that it is using the modern forwarding protocol.&lt;br /&gt;
 nano ~/velocity/velocity.toml&lt;br /&gt;
Modify these specific lines:&lt;br /&gt;
* Bind Address: bind = &amp;quot;0.0.0.0:25565&amp;quot; (Allows it to hear traffic from pfSense).&lt;br /&gt;
* Forwarding Mode: player-info-forwarding-mode = &amp;quot;modern&amp;quot; (This is the most secure protocol for 2026).&lt;br /&gt;
* ping-passthrough should be set to ALL. This is to ensure the server list on the Minecraft client correctly displays the status and version of the backend servers&lt;br /&gt;
* Server List: Scroll down to the [servers] section:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[servers]&lt;br /&gt;
 cherry = &amp;quot;192.168.100.30:25565&amp;quot;&lt;br /&gt;
 apple = &amp;quot;192.168.100.35:25565&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 [servers]&lt;br /&gt;
 try = [&lt;br /&gt;
    &amp;quot;cherry&amp;quot;&lt;br /&gt;
 ]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Forced Hosts: This tells the proxy which server to pick based on the URL the player typed:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[forced-hosts]&lt;br /&gt;
 &amp;quot;cherry.seaoffate.net&amp;quot; = [&amp;quot;cherry&amp;quot;]&lt;br /&gt;
 &amp;quot;apple.seaoffate.net&amp;quot; = [&amp;quot;apple&amp;quot;]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Save and close the file. next we need a start.sh file for Velocity &lt;br /&gt;
 nano ~/velocity/start.sh&lt;br /&gt;
copy the following into the file&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Vangueria Proxy ---&amp;quot;&lt;br /&gt;
     java -Xms512M -Xmx512M \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar velocity.jar&lt;br /&gt;
     echo &amp;quot;--- Proxy stopped. Restarting in 5s ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
To make the script executable &lt;br /&gt;
 chmod +x ~/velocity/start.sh&lt;br /&gt;
At this point the since Vangueria is now set to Modern Forwarding, Cherry will reject all connections until it has the forwarding.secret. the secret can be obtained with the command&lt;br /&gt;
 cat ~/velocity/forwarding.secret&lt;br /&gt;
Copy the code to a safe location because we will need it to setup cherry (and apple). then we should be able to finally start the proxy with the start.sh&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now we move to cherry to setup it&#039;s ability to receive connections from Vangueria. &lt;br /&gt;
&lt;br /&gt;
====Configuring Cherry To Accept Proxied Connections====&lt;br /&gt;
&lt;br /&gt;
To complete the integration between the proxy and the backend, Cherry must be transitioned from a standalone Vanilla server to a &amp;quot;Proxy-Aware&amp;quot; host. Because Vanilla Minecraft does not natively support Velocity’s Modern Forwarding (the security handshake), we use the Fabric Loader as a lightweight wrapper. This allows us to install a bridge mod that validates the secret key without changing the gameplay experience.The transition of Cherry involves three main phases: installing the Fabric environment, adding the bridge mods, and configuring the security handshake to match Vangueria.&lt;br /&gt;
&lt;br /&gt;
First, we must stop the existing server and install the Fabric transition layer. This replaces the standard Mojang launcher with a version capable of loading the security bridge. We need to download the Fabric Installer and then Install Fabric for the 1.21.1 environment.&lt;br /&gt;
 cd ~/minecraft_server&lt;br /&gt;
 wget https://maven.fabricmc.net/net/fabricmc/fabric-installer/1.0.1/fabric-installer-1.0.1.jar&lt;br /&gt;
 java -jar fabric-installer-1.0.1.jar server -mcversion 1.21.1 -downloadMinecraft&lt;br /&gt;
Once complete, the installer will have created a new file named fabric-server-launch.jar. This is now the primary entry point for the server.&lt;br /&gt;
&lt;br /&gt;
To install the Security Bridge we require two specific components in the mods folder: the Fabric API (the library that allows mods to interact with the game engine) and FabricProxy-Lite (the specific mod that handles the Velocity secret key). It is vital to use version-matched JARs for 1.21.1 to ensure stability.&lt;br /&gt;
 mkdir -p ~/minecraft_server/mods&lt;br /&gt;
 wget -O ~/minecraft_server/mods/FabricProxy-Lite.jar https://github.com/OKTW-Network/FabricProxy-Lite/releases/download/v2.10.1/FabricProxy-Lite-2.10.1.jar&lt;br /&gt;
 wget -O ~/minecraft_server/mods/fabric-api.jar https://github.com/FabricMC/fabric-api/releases/download/0.116.11%2B1.21.1/fabric-api-0.116.11+1.21.1.jar&lt;br /&gt;
&lt;br /&gt;
To configure the handshake after placing the mods, we must run the server once to generate the configuration structure, then shut it down to inject the secret.&lt;br /&gt;
Update start.sh to point to fabric-server-launch.jar instead of server.jar&lt;br /&gt;
 sed -i &#039;s/server.jar/fabric-server-launch.jar/&#039; start.sh&lt;br /&gt;
Initial run to generate config (Type &#039;stop&#039; once the &#039;Done&#039; message appears)&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now, we create the configuration file and link it to Vangueria. This is where we ensure the backend only trusts traffic coming from our proxy.&lt;br /&gt;
 mkdir -p ~/minecraft_server/config&lt;br /&gt;
 nano ~/minecraft_server/config/FabricProxy-Lite.toml&lt;br /&gt;
Paste the following configuration into the file, ensuring the secret matches the one obtained from Vangueria:&lt;br /&gt;
 enabled = true&lt;br /&gt;
 hackOnlineMode = true&lt;br /&gt;
 secret = &amp;quot;PASTE_YOUR_VANGUERIA_SECRET_HERE&amp;quot;&lt;br /&gt;
The final step is to adjust the server.properties file. Because Vangueria handles the official Mojang authentication at the &amp;quot;front door,&amp;quot; the backend server must be set to offline mode to allow the proxy to pass the authenticated user data through.&lt;br /&gt;
 sed -i &#039;s/online-mode=true/online-mode=false/&#039; server.properties&lt;br /&gt;
With the configuration complete, the server should be launched inside a named screen session to ensure it remains active.&lt;br /&gt;
 screen -S minecraft ./start.sh&lt;br /&gt;
We should now change the Pfsense port forward rule to forward traffic to the 192.168.100.29 (IP address of Vangueria) and then connecting a client from a laptop outside of Pfsense and using the address cherry.seaoffate.net, we can try using the IP address of the Pfsense WAN port but it may not work (if the default server is set to cherry it may connect)&lt;br /&gt;
&lt;br /&gt;
===Additional Options===&lt;br /&gt;
&lt;br /&gt;
There are a few additional considerations that will make the servers run more reliably. The first is thing that needs to be done is to run the server in a screen so that there does not need to be a SSH session to be running. The following will start a screen called minecraft and will execute the start.sh command. &lt;br /&gt;
 screen -S minecraft ./start&lt;br /&gt;
To exit the minecraft screen and return to the main SSH type ctrl + a and then d, the minecraft screen can be reloaded with the command &lt;br /&gt;
 screen -r minecraft&lt;br /&gt;
The next thing that we will need to do is to have the minecraft server start whenever the host reboots. So we need to add a cron tab to the start.sh&lt;br /&gt;
 crontab -e&lt;br /&gt;
Select nano if asked then add the line &lt;br /&gt;
 @reboot screen -dmS minecraft /home/nigel/minecraft_server/start.sh&lt;br /&gt;
&lt;br /&gt;
The next thing is not a minecraft helper exactly but it will be useful as a reminder in the future. When a user logs on to the host the message of the day will be displayed to add simple notes to the message we can simply edit the motd with the command&lt;br /&gt;
 sudo nano /etc/motd&lt;br /&gt;
&lt;br /&gt;
===Adding a second Minecraft server Apple===&lt;br /&gt;
&lt;br /&gt;
Now that we have the basic setup with potential for multiple hosts we will need to create at least one more so that we can prove the proxy works as intended. The next server will be a different version with some mods. As soon as we start adding mods to a Minecraft world they will use more resources so we will need the next host to be a bit better specified.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 5 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 14GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 150GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Apple||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.35 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
&lt;br /&gt;
As we did with the cherry host earlier we need to configure the hardware changes that have been made on the basic specification like adding the Lexar HD as the swap file. We must stop using the swap partition on the primary drive so we can move it out of the way. Turn off all swap.&lt;br /&gt;
 sudo swapoff -a&lt;br /&gt;
Since your swap partition (sda3) is at the end of the disk, it acts as a &amp;quot;blocker.&amp;quot; We need to delete it and the root partition, then recreate the root partition to fill the entire space.&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
* Type p to print the table (confirming sda2 is root and sda3 is swap).&lt;br /&gt;
* Type d then 3 to delete the swap partition.&lt;br /&gt;
* Type d then 2 to delete the root partition (Don&#039;t worry, the data stays in the blocks).&lt;br /&gt;
* Step B: Recreate and Expand&lt;br /&gt;
* Type n for a new partition.&lt;br /&gt;
* Type p for Primary. Note if disk is using a GPT (GUID Partition Table) there will be no P option, primary partitions only exist in the old MBR style of disks&lt;br /&gt;
* Type 2 for Partition number 2.&lt;br /&gt;
* Press Enter for the default Start Sector (it must match the old start sector of sda2).&lt;br /&gt;
* Press Enter for the default End Sector (this will now jump to the end of the 150GB disk).&lt;br /&gt;
* CRITICAL: When it asks &amp;quot;Do you want to remove the signature?&amp;quot;, type N.&lt;br /&gt;
* Type w to write changes and exit.&lt;br /&gt;
Now, reboot to make sure the kernel is looking at the new 150GB table entry.&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
Once you log back in, expand the actual data &amp;quot;container&amp;quot; (the ext4 filesystem) to fill that new partition:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
Now that the main drive is expanded, let&#039;s get that high-speed swap set up on your 16GB secondary disk.&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
We need to update /etc/fstab so your VM knows where to find its memory &amp;quot;safety net&amp;quot; on every boot.&lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Look for the line that mentions the old swap (it likely mentions sda3 or a long UUID string). Delete that line or put a # at the start of it. Add this new line at the bottom:&lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
Save and exit. Then to confirm the changes have been made use the following commands to show the new sda2 disk size and the swap disk&lt;br /&gt;
 df -h&lt;br /&gt;
 free -h&lt;br /&gt;
&lt;br /&gt;
====Software installation====&lt;br /&gt;
&lt;br /&gt;
Since Apple is a fresh VM, we need to ensure the underlying Debian OS is fully patched and has the necessary build tools and repositories before we drop a massive modpack into it. Modern modpacks like ATM10 (Minecraft 1.21.1) rely heavily on Java 21 or Java 25, so we will set that foundation now. First, we refresh the local package index and upgrade any existing system components. Update package lists and upgrade system and install essential utilities for file management and monitoring&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
 sudo apt install -y htop screen wget curl jq unzip zip&lt;br /&gt;
Install Java 25 and verify the version to ensure it&#039;s active&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless&lt;br /&gt;
 java -version&lt;br /&gt;
Now that the system is ready, we can create the home for Apple. Create the Modpack Directory&lt;br /&gt;
 mkdir ~/atm_server &amp;amp;&amp;amp; cd ~/atm_server&lt;br /&gt;
We now need the server file ServerFiles-6.6.zip but it would appear that the curseforge website don&#039;t allow wget downloads so the best way to get the file is to download via http and scp it to the atm-server directory. When the .zip file is in the atm directory we unzip it&lt;br /&gt;
 unzip ServerFiles-6.6.zip&lt;br /&gt;
Make the installer executable&lt;br /&gt;
 chmod +x startserver.sh&lt;br /&gt;
Run the installer&lt;br /&gt;
 ./startserver.sh&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1541</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1541"/>
		<updated>2026-05-12T20:43:17Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Hardware Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
The first Minecraft host needs to have enough resources to run the JVM and the server but as it just a vanilla server the specification does not need to be excessive. The table shows the highlights.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;br /&gt;
&lt;br /&gt;
===Velocity Installation===&lt;br /&gt;
&lt;br /&gt;
The Velocity server VM does not need to be especially high because all it needs to do is accept connections and forward them on to the relevant host and any associated functions like handle logon, bans and etc. Unlike the cherry host that we just setup the base specification from the Debian template needs to be cut down a bit and does not need a extra swap file or anything special.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 1 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 1GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Storage || 32GB ||  &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Vangueria ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.29 ||&lt;br /&gt;
|}&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
As there is no additions to the VM&#039;s specification there is no hardware to configure so we can get straight to the software installation. So the well known update/upgrade and the packages can be installed with&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless htop screen wget jq curl&lt;br /&gt;
Once the dependencies are installed, we create a dedicated application directory and use an automated script to identify the most recent build of Velocity 3.4.0. This ensures we are not relying on hardcoded links that may expire.&lt;br /&gt;
 mkdir ~/velocity &amp;amp;&amp;amp; cd ~/velocity&lt;br /&gt;
 export PROJECT=&amp;quot;velocity&amp;quot;&lt;br /&gt;
 export VERSION=&amp;quot;3.4.0-SNAPSHOT&amp;quot;&lt;br /&gt;
 export LATEST_BUILD=$(curl -s https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION} | jq &#039;.builds[-1]&#039;)&lt;br /&gt;
 wget -O ~/velocity/velocity.jar &amp;quot;https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION}/builds/${LATEST_BUILD}/downloads/${PROJECT}-${VERSION}-${LATEST_BUILD}.jar&amp;quot;&lt;br /&gt;
The initial boot of Velocity is performed to generate the necessary configuration files. We launch it with a 512MB heap size and then shut it down gracefully using the end command once the prompt appears.&lt;br /&gt;
 java -Xms512M -Xmx512M -jar velocity.jar&lt;br /&gt;
&lt;br /&gt;
====Proxy Configuration and Routing====&lt;br /&gt;
&lt;br /&gt;
The primary configuration for the proxy is handled within the velocity.toml file. This file dictates how the proxy listens for incoming traffic and how it maps domain names to internal IP addresses. We edit this file to ensure the proxy is listening on all interfaces and that it is using the modern forwarding protocol.&lt;br /&gt;
 nano ~/velocity/velocity.toml&lt;br /&gt;
Modify these specific lines:&lt;br /&gt;
* Bind Address: bind = &amp;quot;0.0.0.0:25565&amp;quot; (Allows it to hear traffic from pfSense).&lt;br /&gt;
* Forwarding Mode: player-info-forwarding-mode = &amp;quot;modern&amp;quot; (This is the most secure protocol for 2026).&lt;br /&gt;
* ping-passthrough should be set to ALL. This is to ensure the server list on the Minecraft client correctly displays the status and version of the backend servers&lt;br /&gt;
* Server List: Scroll down to the [servers] section:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[servers]&lt;br /&gt;
 cherry = &amp;quot;192.168.100.30:25565&amp;quot;&lt;br /&gt;
 apple = &amp;quot;192.168.100.35:25565&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 [servers]&lt;br /&gt;
 try = [&lt;br /&gt;
    &amp;quot;cherry&amp;quot;&lt;br /&gt;
 ]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Forced Hosts: This tells the proxy which server to pick based on the URL the player typed:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[forced-hosts]&lt;br /&gt;
 &amp;quot;cherry.seaoffate.net&amp;quot; = [&amp;quot;cherry&amp;quot;]&lt;br /&gt;
 &amp;quot;apple.seaoffate.net&amp;quot; = [&amp;quot;apple&amp;quot;]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Save and close the file. next we need a start.sh file for Velocity &lt;br /&gt;
 nano ~/velocity/start.sh&lt;br /&gt;
copy the following into the file&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Vangueria Proxy ---&amp;quot;&lt;br /&gt;
     java -Xms512M -Xmx512M \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar velocity.jar&lt;br /&gt;
     echo &amp;quot;--- Proxy stopped. Restarting in 5s ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
To make the script executable &lt;br /&gt;
 chmod +x ~/velocity/start.sh&lt;br /&gt;
At this point the since Vangueria is now set to Modern Forwarding, Cherry will reject all connections until it has the forwarding.secret. the secret can be obtained with the command&lt;br /&gt;
 cat ~/velocity/forwarding.secret&lt;br /&gt;
Copy the code to a safe location because we will need it to setup cherry (and apple). then we should be able to finally start the proxy with the start.sh&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now we move to cherry to setup it&#039;s ability to receive connections from Vangueria. &lt;br /&gt;
&lt;br /&gt;
====Configuring Cherry To Accept Proxied Connections====&lt;br /&gt;
&lt;br /&gt;
To complete the integration between the proxy and the backend, Cherry must be transitioned from a standalone Vanilla server to a &amp;quot;Proxy-Aware&amp;quot; host. Because Vanilla Minecraft does not natively support Velocity’s Modern Forwarding (the security handshake), we use the Fabric Loader as a lightweight wrapper. This allows us to install a bridge mod that validates the secret key without changing the gameplay experience.The transition of Cherry involves three main phases: installing the Fabric environment, adding the bridge mods, and configuring the security handshake to match Vangueria.&lt;br /&gt;
&lt;br /&gt;
First, we must stop the existing server and install the Fabric transition layer. This replaces the standard Mojang launcher with a version capable of loading the security bridge. We need to download the Fabric Installer and then Install Fabric for the 1.21.1 environment.&lt;br /&gt;
 cd ~/minecraft_server&lt;br /&gt;
 wget https://maven.fabricmc.net/net/fabricmc/fabric-installer/1.0.1/fabric-installer-1.0.1.jar&lt;br /&gt;
 java -jar fabric-installer-1.0.1.jar server -mcversion 1.21.1 -downloadMinecraft&lt;br /&gt;
Once complete, the installer will have created a new file named fabric-server-launch.jar. This is now the primary entry point for the server.&lt;br /&gt;
&lt;br /&gt;
To install the Security Bridge we require two specific components in the mods folder: the Fabric API (the library that allows mods to interact with the game engine) and FabricProxy-Lite (the specific mod that handles the Velocity secret key). It is vital to use version-matched JARs for 1.21.1 to ensure stability.&lt;br /&gt;
 mkdir -p ~/minecraft_server/mods&lt;br /&gt;
 wget -O ~/minecraft_server/mods/FabricProxy-Lite.jar https://github.com/OKTW-Network/FabricProxy-Lite/releases/download/v2.10.1/FabricProxy-Lite-2.10.1.jar&lt;br /&gt;
 wget -O ~/minecraft_server/mods/fabric-api.jar https://github.com/FabricMC/fabric-api/releases/download/0.116.11%2B1.21.1/fabric-api-0.116.11+1.21.1.jar&lt;br /&gt;
&lt;br /&gt;
To configure the handshake after placing the mods, we must run the server once to generate the configuration structure, then shut it down to inject the secret.&lt;br /&gt;
Update start.sh to point to fabric-server-launch.jar instead of server.jar&lt;br /&gt;
 sed -i &#039;s/server.jar/fabric-server-launch.jar/&#039; start.sh&lt;br /&gt;
Initial run to generate config (Type &#039;stop&#039; once the &#039;Done&#039; message appears)&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now, we create the configuration file and link it to Vangueria. This is where we ensure the backend only trusts traffic coming from our proxy.&lt;br /&gt;
 mkdir -p ~/minecraft_server/config&lt;br /&gt;
 nano ~/minecraft_server/config/FabricProxy-Lite.toml&lt;br /&gt;
Paste the following configuration into the file, ensuring the secret matches the one obtained from Vangueria:&lt;br /&gt;
 enabled = true&lt;br /&gt;
 hackOnlineMode = true&lt;br /&gt;
 secret = &amp;quot;PASTE_YOUR_VANGUERIA_SECRET_HERE&amp;quot;&lt;br /&gt;
The final step is to adjust the server.properties file. Because Vangueria handles the official Mojang authentication at the &amp;quot;front door,&amp;quot; the backend server must be set to offline mode to allow the proxy to pass the authenticated user data through.&lt;br /&gt;
 sed -i &#039;s/online-mode=true/online-mode=false/&#039; server.properties&lt;br /&gt;
With the configuration complete, the server should be launched inside a named screen session to ensure it remains active.&lt;br /&gt;
 screen -S minecraft ./start.sh&lt;br /&gt;
We should now change the Pfsense port forward rule to forward traffic to the 192.168.100.29 (IP address of Vangueria) and then connecting a client from a laptop outside of Pfsense and using the address cherry.seaoffate.net, we can try using the IP address of the Pfsense WAN port but it may not work (if the default server is set to cherry it may connect)&lt;br /&gt;
&lt;br /&gt;
===Additional Options===&lt;br /&gt;
&lt;br /&gt;
There are a few additional considerations that will make the servers run more reliably. The first is thing that needs to be done is to run the server in a screen so that there does not need to be a SSH session to be running. The following will start a screen called minecraft and will execute the start.sh command. &lt;br /&gt;
 screen -S minecraft ./start&lt;br /&gt;
To exit the minecraft screen and return to the main SSH type ctrl + a and then d, the minecraft screen can be reloaded with the command &lt;br /&gt;
 screen -r minecraft&lt;br /&gt;
The next thing that we will need to do is to have the minecraft server start whenever the host reboots. So we need to add a cron tab to the start.sh&lt;br /&gt;
 crontab -e&lt;br /&gt;
Select nano if asked then add the line &lt;br /&gt;
 @reboot screen -dmS minecraft /home/nigel/minecraft_server/start.sh&lt;br /&gt;
&lt;br /&gt;
The next thing is not a minecraft helper exactly but it will be useful as a reminder in the future. When a user logs on to the host the message of the day will be displayed to add simple notes to the message we can simply edit the motd with the command&lt;br /&gt;
 sudo nano /etc/motd&lt;br /&gt;
&lt;br /&gt;
===Adding a second Minecraft server Apple===&lt;br /&gt;
&lt;br /&gt;
Now that we have the basic setup with potential for multiple hosts we will need to create at least one more so that we can prove the proxy works as intended. The next server will be a different version with some mods. As soon as we start adding mods to a Minecraft world they will use more resources so we will need the next host to be a bit better specified.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 5 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 14GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 150GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Apple||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.35 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
&lt;br /&gt;
As we did with the cherry host earlier we need to configure the hardware changes that have been made on the basic specification like adding the Lexar HD as the swap file. We must stop using the swap partition on the primary drive so we can move it out of the way. Turn off all swap.&lt;br /&gt;
 sudo swapoff -a&lt;br /&gt;
Since your swap partition (sda3) is at the end of the disk, it acts as a &amp;quot;blocker.&amp;quot; We need to delete it and the root partition, then recreate the root partition to fill the entire space.&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
* Type p to print the table (confirming sda2 is root and sda3 is swap).&lt;br /&gt;
* Type d then 3 to delete the swap partition.&lt;br /&gt;
* Type d then 2 to delete the root partition (Don&#039;t worry, the data stays in the blocks).&lt;br /&gt;
* Step B: Recreate and Expand&lt;br /&gt;
* Type n for a new partition.&lt;br /&gt;
* Type p for Primary. Note if disk is using a GPT (GUID Partition Table) there will be no P option, primary partitions only exist in the old MBR style of disks&lt;br /&gt;
* Type 2 for Partition number 2.&lt;br /&gt;
* Press Enter for the default Start Sector (it must match the old start sector of sda2).&lt;br /&gt;
* Press Enter for the default End Sector (this will now jump to the end of the 150GB disk).&lt;br /&gt;
* CRITICAL: When it asks &amp;quot;Do you want to remove the signature?&amp;quot;, type N.&lt;br /&gt;
* Type w to write changes and exit.&lt;br /&gt;
Now, reboot to make sure the kernel is looking at the new 150GB table entry.&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
Once you log back in, expand the actual data &amp;quot;container&amp;quot; (the ext4 filesystem) to fill that new partition:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
Now that the main drive is expanded, let&#039;s get that high-speed swap set up on your 16GB secondary disk.&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
We need to update /etc/fstab so your VM knows where to find its memory &amp;quot;safety net&amp;quot; on every boot.&lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Look for the line that mentions the old swap (it likely mentions sda3 or a long UUID string). Delete that line or put a # at the start of it. Add this new line at the bottom:&lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
Save and exit. Then to confirm the changes have been made use the following commands to show the new sda2 disk size and the swap disk&lt;br /&gt;
 df -h&lt;br /&gt;
 free -h&lt;br /&gt;
&lt;br /&gt;
====Software installation====&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1540</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1540"/>
		<updated>2026-05-12T20:07:02Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Adding a second Minecraft server Apple */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
The first Minecraft host needs to have enough resources to run the JVM and the server but as it just a vanilla server the specification does not need to be excessive. The table shows the highlights.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;br /&gt;
&lt;br /&gt;
===Velocity Installation===&lt;br /&gt;
&lt;br /&gt;
The Velocity server VM does not need to be especially high because all it needs to do is accept connections and forward them on to the relevant host and any associated functions like handle logon, bans and etc. Unlike the cherry host that we just setup the base specification from the Debian template needs to be cut down a bit and does not need a extra swap file or anything special.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 1 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 1GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Storage || 32GB ||  &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Vangueria ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.29 ||&lt;br /&gt;
|}&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
As there is no additions to the VM&#039;s specification there is no hardware to configure so we can get straight to the software installation. So the well known update/upgrade and the packages can be installed with&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless htop screen wget jq curl&lt;br /&gt;
Once the dependencies are installed, we create a dedicated application directory and use an automated script to identify the most recent build of Velocity 3.4.0. This ensures we are not relying on hardcoded links that may expire.&lt;br /&gt;
 mkdir ~/velocity &amp;amp;&amp;amp; cd ~/velocity&lt;br /&gt;
 export PROJECT=&amp;quot;velocity&amp;quot;&lt;br /&gt;
 export VERSION=&amp;quot;3.4.0-SNAPSHOT&amp;quot;&lt;br /&gt;
 export LATEST_BUILD=$(curl -s https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION} | jq &#039;.builds[-1]&#039;)&lt;br /&gt;
 wget -O ~/velocity/velocity.jar &amp;quot;https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION}/builds/${LATEST_BUILD}/downloads/${PROJECT}-${VERSION}-${LATEST_BUILD}.jar&amp;quot;&lt;br /&gt;
The initial boot of Velocity is performed to generate the necessary configuration files. We launch it with a 512MB heap size and then shut it down gracefully using the end command once the prompt appears.&lt;br /&gt;
 java -Xms512M -Xmx512M -jar velocity.jar&lt;br /&gt;
&lt;br /&gt;
====Proxy Configuration and Routing====&lt;br /&gt;
&lt;br /&gt;
The primary configuration for the proxy is handled within the velocity.toml file. This file dictates how the proxy listens for incoming traffic and how it maps domain names to internal IP addresses. We edit this file to ensure the proxy is listening on all interfaces and that it is using the modern forwarding protocol.&lt;br /&gt;
 nano ~/velocity/velocity.toml&lt;br /&gt;
Modify these specific lines:&lt;br /&gt;
* Bind Address: bind = &amp;quot;0.0.0.0:25565&amp;quot; (Allows it to hear traffic from pfSense).&lt;br /&gt;
* Forwarding Mode: player-info-forwarding-mode = &amp;quot;modern&amp;quot; (This is the most secure protocol for 2026).&lt;br /&gt;
* ping-passthrough should be set to ALL. This is to ensure the server list on the Minecraft client correctly displays the status and version of the backend servers&lt;br /&gt;
* Server List: Scroll down to the [servers] section:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[servers]&lt;br /&gt;
 cherry = &amp;quot;192.168.100.30:25565&amp;quot;&lt;br /&gt;
 apple = &amp;quot;192.168.100.35:25565&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 [servers]&lt;br /&gt;
 try = [&lt;br /&gt;
    &amp;quot;cherry&amp;quot;&lt;br /&gt;
 ]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Forced Hosts: This tells the proxy which server to pick based on the URL the player typed:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[forced-hosts]&lt;br /&gt;
 &amp;quot;cherry.seaoffate.net&amp;quot; = [&amp;quot;cherry&amp;quot;]&lt;br /&gt;
 &amp;quot;apple.seaoffate.net&amp;quot; = [&amp;quot;apple&amp;quot;]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Save and close the file. next we need a start.sh file for Velocity &lt;br /&gt;
 nano ~/velocity/start.sh&lt;br /&gt;
copy the following into the file&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Vangueria Proxy ---&amp;quot;&lt;br /&gt;
     java -Xms512M -Xmx512M \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar velocity.jar&lt;br /&gt;
     echo &amp;quot;--- Proxy stopped. Restarting in 5s ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
To make the script executable &lt;br /&gt;
 chmod +x ~/velocity/start.sh&lt;br /&gt;
At this point the since Vangueria is now set to Modern Forwarding, Cherry will reject all connections until it has the forwarding.secret. the secret can be obtained with the command&lt;br /&gt;
 cat ~/velocity/forwarding.secret&lt;br /&gt;
Copy the code to a safe location because we will need it to setup cherry (and apple). then we should be able to finally start the proxy with the start.sh&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now we move to cherry to setup it&#039;s ability to receive connections from Vangueria. &lt;br /&gt;
&lt;br /&gt;
====Configuring Cherry To Accept Proxied Connections====&lt;br /&gt;
&lt;br /&gt;
To complete the integration between the proxy and the backend, Cherry must be transitioned from a standalone Vanilla server to a &amp;quot;Proxy-Aware&amp;quot; host. Because Vanilla Minecraft does not natively support Velocity’s Modern Forwarding (the security handshake), we use the Fabric Loader as a lightweight wrapper. This allows us to install a bridge mod that validates the secret key without changing the gameplay experience.The transition of Cherry involves three main phases: installing the Fabric environment, adding the bridge mods, and configuring the security handshake to match Vangueria.&lt;br /&gt;
&lt;br /&gt;
First, we must stop the existing server and install the Fabric transition layer. This replaces the standard Mojang launcher with a version capable of loading the security bridge. We need to download the Fabric Installer and then Install Fabric for the 1.21.1 environment.&lt;br /&gt;
 cd ~/minecraft_server&lt;br /&gt;
 wget https://maven.fabricmc.net/net/fabricmc/fabric-installer/1.0.1/fabric-installer-1.0.1.jar&lt;br /&gt;
 java -jar fabric-installer-1.0.1.jar server -mcversion 1.21.1 -downloadMinecraft&lt;br /&gt;
Once complete, the installer will have created a new file named fabric-server-launch.jar. This is now the primary entry point for the server.&lt;br /&gt;
&lt;br /&gt;
To install the Security Bridge we require two specific components in the mods folder: the Fabric API (the library that allows mods to interact with the game engine) and FabricProxy-Lite (the specific mod that handles the Velocity secret key). It is vital to use version-matched JARs for 1.21.1 to ensure stability.&lt;br /&gt;
 mkdir -p ~/minecraft_server/mods&lt;br /&gt;
 wget -O ~/minecraft_server/mods/FabricProxy-Lite.jar https://github.com/OKTW-Network/FabricProxy-Lite/releases/download/v2.10.1/FabricProxy-Lite-2.10.1.jar&lt;br /&gt;
 wget -O ~/minecraft_server/mods/fabric-api.jar https://github.com/FabricMC/fabric-api/releases/download/0.116.11%2B1.21.1/fabric-api-0.116.11+1.21.1.jar&lt;br /&gt;
&lt;br /&gt;
To configure the handshake after placing the mods, we must run the server once to generate the configuration structure, then shut it down to inject the secret.&lt;br /&gt;
Update start.sh to point to fabric-server-launch.jar instead of server.jar&lt;br /&gt;
 sed -i &#039;s/server.jar/fabric-server-launch.jar/&#039; start.sh&lt;br /&gt;
Initial run to generate config (Type &#039;stop&#039; once the &#039;Done&#039; message appears)&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now, we create the configuration file and link it to Vangueria. This is where we ensure the backend only trusts traffic coming from our proxy.&lt;br /&gt;
 mkdir -p ~/minecraft_server/config&lt;br /&gt;
 nano ~/minecraft_server/config/FabricProxy-Lite.toml&lt;br /&gt;
Paste the following configuration into the file, ensuring the secret matches the one obtained from Vangueria:&lt;br /&gt;
 enabled = true&lt;br /&gt;
 hackOnlineMode = true&lt;br /&gt;
 secret = &amp;quot;PASTE_YOUR_VANGUERIA_SECRET_HERE&amp;quot;&lt;br /&gt;
The final step is to adjust the server.properties file. Because Vangueria handles the official Mojang authentication at the &amp;quot;front door,&amp;quot; the backend server must be set to offline mode to allow the proxy to pass the authenticated user data through.&lt;br /&gt;
 sed -i &#039;s/online-mode=true/online-mode=false/&#039; server.properties&lt;br /&gt;
With the configuration complete, the server should be launched inside a named screen session to ensure it remains active.&lt;br /&gt;
 screen -S minecraft ./start.sh&lt;br /&gt;
We should now change the Pfsense port forward rule to forward traffic to the 192.168.100.29 (IP address of Vangueria) and then connecting a client from a laptop outside of Pfsense and using the address cherry.seaoffate.net, we can try using the IP address of the Pfsense WAN port but it may not work (if the default server is set to cherry it may connect)&lt;br /&gt;
&lt;br /&gt;
===Additional Options===&lt;br /&gt;
&lt;br /&gt;
There are a few additional considerations that will make the servers run more reliably. The first is thing that needs to be done is to run the server in a screen so that there does not need to be a SSH session to be running. The following will start a screen called minecraft and will execute the start.sh command. &lt;br /&gt;
 screen -S minecraft ./start&lt;br /&gt;
To exit the minecraft screen and return to the main SSH type ctrl + a and then d, the minecraft screen can be reloaded with the command &lt;br /&gt;
 screen -r minecraft&lt;br /&gt;
The next thing that we will need to do is to have the minecraft server start whenever the host reboots. So we need to add a cron tab to the start.sh&lt;br /&gt;
 crontab -e&lt;br /&gt;
Select nano if asked then add the line &lt;br /&gt;
 @reboot screen -dmS minecraft /home/nigel/minecraft_server/start.sh&lt;br /&gt;
&lt;br /&gt;
The next thing is not a minecraft helper exactly but it will be useful as a reminder in the future. When a user logs on to the host the message of the day will be displayed to add simple notes to the message we can simply edit the motd with the command&lt;br /&gt;
 sudo nano /etc/motd&lt;br /&gt;
&lt;br /&gt;
===Adding a second Minecraft server Apple===&lt;br /&gt;
&lt;br /&gt;
Now that we have the basic setup with potential for multiple hosts we will need to create at least one more so that we can prove the proxy works as intended. The next server will be a different version with some mods. As soon as we start adding mods to a Minecraft world they will use more resources so we will need the next host to be a bit better specified.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 5 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 14GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 150GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Apple||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.35 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
&lt;br /&gt;
As we did with the cherry host earlier we need to configure the hardware changes that have been made on the basic specification like adding the Lexar HD as the swap file. The fast config of the swap is to initialize the partition as swap, enable the swap immediately and add to /etc/fstab for persistence&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1539</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1539"/>
		<updated>2026-05-12T18:50:56Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Adding a second Minecraft server Apple */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
The first Minecraft host needs to have enough resources to run the JVM and the server but as it just a vanilla server the specification does not need to be excessive. The table shows the highlights.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;br /&gt;
&lt;br /&gt;
===Velocity Installation===&lt;br /&gt;
&lt;br /&gt;
The Velocity server VM does not need to be especially high because all it needs to do is accept connections and forward them on to the relevant host and any associated functions like handle logon, bans and etc. Unlike the cherry host that we just setup the base specification from the Debian template needs to be cut down a bit and does not need a extra swap file or anything special.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 1 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 1GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Storage || 32GB ||  &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Vangueria ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.29 ||&lt;br /&gt;
|}&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
As there is no additions to the VM&#039;s specification there is no hardware to configure so we can get straight to the software installation. So the well known update/upgrade and the packages can be installed with&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless htop screen wget jq curl&lt;br /&gt;
Once the dependencies are installed, we create a dedicated application directory and use an automated script to identify the most recent build of Velocity 3.4.0. This ensures we are not relying on hardcoded links that may expire.&lt;br /&gt;
 mkdir ~/velocity &amp;amp;&amp;amp; cd ~/velocity&lt;br /&gt;
 export PROJECT=&amp;quot;velocity&amp;quot;&lt;br /&gt;
 export VERSION=&amp;quot;3.4.0-SNAPSHOT&amp;quot;&lt;br /&gt;
 export LATEST_BUILD=$(curl -s https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION} | jq &#039;.builds[-1]&#039;)&lt;br /&gt;
 wget -O ~/velocity/velocity.jar &amp;quot;https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION}/builds/${LATEST_BUILD}/downloads/${PROJECT}-${VERSION}-${LATEST_BUILD}.jar&amp;quot;&lt;br /&gt;
The initial boot of Velocity is performed to generate the necessary configuration files. We launch it with a 512MB heap size and then shut it down gracefully using the end command once the prompt appears.&lt;br /&gt;
 java -Xms512M -Xmx512M -jar velocity.jar&lt;br /&gt;
&lt;br /&gt;
====Proxy Configuration and Routing====&lt;br /&gt;
&lt;br /&gt;
The primary configuration for the proxy is handled within the velocity.toml file. This file dictates how the proxy listens for incoming traffic and how it maps domain names to internal IP addresses. We edit this file to ensure the proxy is listening on all interfaces and that it is using the modern forwarding protocol.&lt;br /&gt;
 nano ~/velocity/velocity.toml&lt;br /&gt;
Modify these specific lines:&lt;br /&gt;
* Bind Address: bind = &amp;quot;0.0.0.0:25565&amp;quot; (Allows it to hear traffic from pfSense).&lt;br /&gt;
* Forwarding Mode: player-info-forwarding-mode = &amp;quot;modern&amp;quot; (This is the most secure protocol for 2026).&lt;br /&gt;
* ping-passthrough should be set to ALL. This is to ensure the server list on the Minecraft client correctly displays the status and version of the backend servers&lt;br /&gt;
* Server List: Scroll down to the [servers] section:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[servers]&lt;br /&gt;
 cherry = &amp;quot;192.168.100.30:25565&amp;quot;&lt;br /&gt;
 apple = &amp;quot;192.168.100.35:25565&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 [servers]&lt;br /&gt;
 try = [&lt;br /&gt;
    &amp;quot;cherry&amp;quot;&lt;br /&gt;
 ]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Forced Hosts: This tells the proxy which server to pick based on the URL the player typed:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[forced-hosts]&lt;br /&gt;
 &amp;quot;cherry.seaoffate.net&amp;quot; = [&amp;quot;cherry&amp;quot;]&lt;br /&gt;
 &amp;quot;apple.seaoffate.net&amp;quot; = [&amp;quot;apple&amp;quot;]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Save and close the file. next we need a start.sh file for Velocity &lt;br /&gt;
 nano ~/velocity/start.sh&lt;br /&gt;
copy the following into the file&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Vangueria Proxy ---&amp;quot;&lt;br /&gt;
     java -Xms512M -Xmx512M \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar velocity.jar&lt;br /&gt;
     echo &amp;quot;--- Proxy stopped. Restarting in 5s ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
To make the script executable &lt;br /&gt;
 chmod +x ~/velocity/start.sh&lt;br /&gt;
At this point the since Vangueria is now set to Modern Forwarding, Cherry will reject all connections until it has the forwarding.secret. the secret can be obtained with the command&lt;br /&gt;
 cat ~/velocity/forwarding.secret&lt;br /&gt;
Copy the code to a safe location because we will need it to setup cherry (and apple). then we should be able to finally start the proxy with the start.sh&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now we move to cherry to setup it&#039;s ability to receive connections from Vangueria. &lt;br /&gt;
&lt;br /&gt;
====Configuring Cherry To Accept Proxied Connections====&lt;br /&gt;
&lt;br /&gt;
To complete the integration between the proxy and the backend, Cherry must be transitioned from a standalone Vanilla server to a &amp;quot;Proxy-Aware&amp;quot; host. Because Vanilla Minecraft does not natively support Velocity’s Modern Forwarding (the security handshake), we use the Fabric Loader as a lightweight wrapper. This allows us to install a bridge mod that validates the secret key without changing the gameplay experience.The transition of Cherry involves three main phases: installing the Fabric environment, adding the bridge mods, and configuring the security handshake to match Vangueria.&lt;br /&gt;
&lt;br /&gt;
First, we must stop the existing server and install the Fabric transition layer. This replaces the standard Mojang launcher with a version capable of loading the security bridge. We need to download the Fabric Installer and then Install Fabric for the 1.21.1 environment.&lt;br /&gt;
 cd ~/minecraft_server&lt;br /&gt;
 wget https://maven.fabricmc.net/net/fabricmc/fabric-installer/1.0.1/fabric-installer-1.0.1.jar&lt;br /&gt;
 java -jar fabric-installer-1.0.1.jar server -mcversion 1.21.1 -downloadMinecraft&lt;br /&gt;
Once complete, the installer will have created a new file named fabric-server-launch.jar. This is now the primary entry point for the server.&lt;br /&gt;
&lt;br /&gt;
To install the Security Bridge we require two specific components in the mods folder: the Fabric API (the library that allows mods to interact with the game engine) and FabricProxy-Lite (the specific mod that handles the Velocity secret key). It is vital to use version-matched JARs for 1.21.1 to ensure stability.&lt;br /&gt;
 mkdir -p ~/minecraft_server/mods&lt;br /&gt;
 wget -O ~/minecraft_server/mods/FabricProxy-Lite.jar https://github.com/OKTW-Network/FabricProxy-Lite/releases/download/v2.10.1/FabricProxy-Lite-2.10.1.jar&lt;br /&gt;
 wget -O ~/minecraft_server/mods/fabric-api.jar https://github.com/FabricMC/fabric-api/releases/download/0.116.11%2B1.21.1/fabric-api-0.116.11+1.21.1.jar&lt;br /&gt;
&lt;br /&gt;
To configure the handshake after placing the mods, we must run the server once to generate the configuration structure, then shut it down to inject the secret.&lt;br /&gt;
Update start.sh to point to fabric-server-launch.jar instead of server.jar&lt;br /&gt;
 sed -i &#039;s/server.jar/fabric-server-launch.jar/&#039; start.sh&lt;br /&gt;
Initial run to generate config (Type &#039;stop&#039; once the &#039;Done&#039; message appears)&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now, we create the configuration file and link it to Vangueria. This is where we ensure the backend only trusts traffic coming from our proxy.&lt;br /&gt;
 mkdir -p ~/minecraft_server/config&lt;br /&gt;
 nano ~/minecraft_server/config/FabricProxy-Lite.toml&lt;br /&gt;
Paste the following configuration into the file, ensuring the secret matches the one obtained from Vangueria:&lt;br /&gt;
 enabled = true&lt;br /&gt;
 hackOnlineMode = true&lt;br /&gt;
 secret = &amp;quot;PASTE_YOUR_VANGUERIA_SECRET_HERE&amp;quot;&lt;br /&gt;
The final step is to adjust the server.properties file. Because Vangueria handles the official Mojang authentication at the &amp;quot;front door,&amp;quot; the backend server must be set to offline mode to allow the proxy to pass the authenticated user data through.&lt;br /&gt;
 sed -i &#039;s/online-mode=true/online-mode=false/&#039; server.properties&lt;br /&gt;
With the configuration complete, the server should be launched inside a named screen session to ensure it remains active.&lt;br /&gt;
 screen -S minecraft ./start.sh&lt;br /&gt;
We should now change the Pfsense port forward rule to forward traffic to the 192.168.100.29 (IP address of Vangueria) and then connecting a client from a laptop outside of Pfsense and using the address cherry.seaoffate.net, we can try using the IP address of the Pfsense WAN port but it may not work (if the default server is set to cherry it may connect)&lt;br /&gt;
&lt;br /&gt;
===Additional Options===&lt;br /&gt;
&lt;br /&gt;
There are a few additional considerations that will make the servers run more reliably. The first is thing that needs to be done is to run the server in a screen so that there does not need to be a SSH session to be running. The following will start a screen called minecraft and will execute the start.sh command. &lt;br /&gt;
 screen -S minecraft ./start&lt;br /&gt;
To exit the minecraft screen and return to the main SSH type ctrl + a and then d, the minecraft screen can be reloaded with the command &lt;br /&gt;
 screen -r minecraft&lt;br /&gt;
The next thing that we will need to do is to have the minecraft server start whenever the host reboots. So we need to add a cron tab to the start.sh&lt;br /&gt;
 crontab -e&lt;br /&gt;
Select nano if asked then add the line &lt;br /&gt;
 @reboot screen -dmS minecraft /home/nigel/minecraft_server/start.sh&lt;br /&gt;
&lt;br /&gt;
The next thing is not a minecraft helper exactly but it will be useful as a reminder in the future. When a user logs on to the host the message of the day will be displayed to add simple notes to the message we can simply edit the motd with the command&lt;br /&gt;
 sudo nano /etc/motd&lt;br /&gt;
&lt;br /&gt;
===Adding a second Minecraft server Apple===&lt;br /&gt;
&lt;br /&gt;
Now that we have the basic setup with potential for multiple hosts we will need to create at least one more so that we can prove the proxy works as intended. The next server will be a different version with some mods. As soon as we start adding mods to a Minecraft world they will use more resources so we will need the next host to be a bit better specified.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 5 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 14GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 150GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Apple||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.35 ||&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1538</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1538"/>
		<updated>2026-05-12T18:24:58Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Adding a second Minecraft server Apple */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
The first Minecraft host needs to have enough resources to run the JVM and the server but as it just a vanilla server the specification does not need to be excessive. The table shows the highlights.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;br /&gt;
&lt;br /&gt;
===Velocity Installation===&lt;br /&gt;
&lt;br /&gt;
The Velocity server VM does not need to be especially high because all it needs to do is accept connections and forward them on to the relevant host and any associated functions like handle logon, bans and etc. Unlike the cherry host that we just setup the base specification from the Debian template needs to be cut down a bit and does not need a extra swap file or anything special.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 1 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 1GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Storage || 32GB ||  &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Vangueria ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.29 ||&lt;br /&gt;
|}&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
As there is no additions to the VM&#039;s specification there is no hardware to configure so we can get straight to the software installation. So the well known update/upgrade and the packages can be installed with&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless htop screen wget jq curl&lt;br /&gt;
Once the dependencies are installed, we create a dedicated application directory and use an automated script to identify the most recent build of Velocity 3.4.0. This ensures we are not relying on hardcoded links that may expire.&lt;br /&gt;
 mkdir ~/velocity &amp;amp;&amp;amp; cd ~/velocity&lt;br /&gt;
 export PROJECT=&amp;quot;velocity&amp;quot;&lt;br /&gt;
 export VERSION=&amp;quot;3.4.0-SNAPSHOT&amp;quot;&lt;br /&gt;
 export LATEST_BUILD=$(curl -s https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION} | jq &#039;.builds[-1]&#039;)&lt;br /&gt;
 wget -O ~/velocity/velocity.jar &amp;quot;https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION}/builds/${LATEST_BUILD}/downloads/${PROJECT}-${VERSION}-${LATEST_BUILD}.jar&amp;quot;&lt;br /&gt;
The initial boot of Velocity is performed to generate the necessary configuration files. We launch it with a 512MB heap size and then shut it down gracefully using the end command once the prompt appears.&lt;br /&gt;
 java -Xms512M -Xmx512M -jar velocity.jar&lt;br /&gt;
&lt;br /&gt;
====Proxy Configuration and Routing====&lt;br /&gt;
&lt;br /&gt;
The primary configuration for the proxy is handled within the velocity.toml file. This file dictates how the proxy listens for incoming traffic and how it maps domain names to internal IP addresses. We edit this file to ensure the proxy is listening on all interfaces and that it is using the modern forwarding protocol.&lt;br /&gt;
 nano ~/velocity/velocity.toml&lt;br /&gt;
Modify these specific lines:&lt;br /&gt;
* Bind Address: bind = &amp;quot;0.0.0.0:25565&amp;quot; (Allows it to hear traffic from pfSense).&lt;br /&gt;
* Forwarding Mode: player-info-forwarding-mode = &amp;quot;modern&amp;quot; (This is the most secure protocol for 2026).&lt;br /&gt;
* ping-passthrough should be set to ALL. This is to ensure the server list on the Minecraft client correctly displays the status and version of the backend servers&lt;br /&gt;
* Server List: Scroll down to the [servers] section:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[servers]&lt;br /&gt;
 cherry = &amp;quot;192.168.100.30:25565&amp;quot;&lt;br /&gt;
 apple = &amp;quot;192.168.100.35:25565&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 [servers]&lt;br /&gt;
 try = [&lt;br /&gt;
    &amp;quot;cherry&amp;quot;&lt;br /&gt;
 ]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Forced Hosts: This tells the proxy which server to pick based on the URL the player typed:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[forced-hosts]&lt;br /&gt;
 &amp;quot;cherry.seaoffate.net&amp;quot; = [&amp;quot;cherry&amp;quot;]&lt;br /&gt;
 &amp;quot;apple.seaoffate.net&amp;quot; = [&amp;quot;apple&amp;quot;]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Save and close the file. next we need a start.sh file for Velocity &lt;br /&gt;
 nano ~/velocity/start.sh&lt;br /&gt;
copy the following into the file&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Vangueria Proxy ---&amp;quot;&lt;br /&gt;
     java -Xms512M -Xmx512M \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar velocity.jar&lt;br /&gt;
     echo &amp;quot;--- Proxy stopped. Restarting in 5s ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
To make the script executable &lt;br /&gt;
 chmod +x ~/velocity/start.sh&lt;br /&gt;
At this point the since Vangueria is now set to Modern Forwarding, Cherry will reject all connections until it has the forwarding.secret. the secret can be obtained with the command&lt;br /&gt;
 cat ~/velocity/forwarding.secret&lt;br /&gt;
Copy the code to a safe location because we will need it to setup cherry (and apple). then we should be able to finally start the proxy with the start.sh&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now we move to cherry to setup it&#039;s ability to receive connections from Vangueria. &lt;br /&gt;
&lt;br /&gt;
====Configuring Cherry To Accept Proxied Connections====&lt;br /&gt;
&lt;br /&gt;
To complete the integration between the proxy and the backend, Cherry must be transitioned from a standalone Vanilla server to a &amp;quot;Proxy-Aware&amp;quot; host. Because Vanilla Minecraft does not natively support Velocity’s Modern Forwarding (the security handshake), we use the Fabric Loader as a lightweight wrapper. This allows us to install a bridge mod that validates the secret key without changing the gameplay experience.The transition of Cherry involves three main phases: installing the Fabric environment, adding the bridge mods, and configuring the security handshake to match Vangueria.&lt;br /&gt;
&lt;br /&gt;
First, we must stop the existing server and install the Fabric transition layer. This replaces the standard Mojang launcher with a version capable of loading the security bridge. We need to download the Fabric Installer and then Install Fabric for the 1.21.1 environment.&lt;br /&gt;
 cd ~/minecraft_server&lt;br /&gt;
 wget https://maven.fabricmc.net/net/fabricmc/fabric-installer/1.0.1/fabric-installer-1.0.1.jar&lt;br /&gt;
 java -jar fabric-installer-1.0.1.jar server -mcversion 1.21.1 -downloadMinecraft&lt;br /&gt;
Once complete, the installer will have created a new file named fabric-server-launch.jar. This is now the primary entry point for the server.&lt;br /&gt;
&lt;br /&gt;
To install the Security Bridge we require two specific components in the mods folder: the Fabric API (the library that allows mods to interact with the game engine) and FabricProxy-Lite (the specific mod that handles the Velocity secret key). It is vital to use version-matched JARs for 1.21.1 to ensure stability.&lt;br /&gt;
 mkdir -p ~/minecraft_server/mods&lt;br /&gt;
 wget -O ~/minecraft_server/mods/FabricProxy-Lite.jar https://github.com/OKTW-Network/FabricProxy-Lite/releases/download/v2.10.1/FabricProxy-Lite-2.10.1.jar&lt;br /&gt;
 wget -O ~/minecraft_server/mods/fabric-api.jar https://github.com/FabricMC/fabric-api/releases/download/0.116.11%2B1.21.1/fabric-api-0.116.11+1.21.1.jar&lt;br /&gt;
&lt;br /&gt;
To configure the handshake after placing the mods, we must run the server once to generate the configuration structure, then shut it down to inject the secret.&lt;br /&gt;
Update start.sh to point to fabric-server-launch.jar instead of server.jar&lt;br /&gt;
 sed -i &#039;s/server.jar/fabric-server-launch.jar/&#039; start.sh&lt;br /&gt;
Initial run to generate config (Type &#039;stop&#039; once the &#039;Done&#039; message appears)&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now, we create the configuration file and link it to Vangueria. This is where we ensure the backend only trusts traffic coming from our proxy.&lt;br /&gt;
 mkdir -p ~/minecraft_server/config&lt;br /&gt;
 nano ~/minecraft_server/config/FabricProxy-Lite.toml&lt;br /&gt;
Paste the following configuration into the file, ensuring the secret matches the one obtained from Vangueria:&lt;br /&gt;
 enabled = true&lt;br /&gt;
 hackOnlineMode = true&lt;br /&gt;
 secret = &amp;quot;PASTE_YOUR_VANGUERIA_SECRET_HERE&amp;quot;&lt;br /&gt;
The final step is to adjust the server.properties file. Because Vangueria handles the official Mojang authentication at the &amp;quot;front door,&amp;quot; the backend server must be set to offline mode to allow the proxy to pass the authenticated user data through.&lt;br /&gt;
 sed -i &#039;s/online-mode=true/online-mode=false/&#039; server.properties&lt;br /&gt;
With the configuration complete, the server should be launched inside a named screen session to ensure it remains active.&lt;br /&gt;
 screen -S minecraft ./start.sh&lt;br /&gt;
We should now change the Pfsense port forward rule to forward traffic to the 192.168.100.29 (IP address of Vangueria) and then connecting a client from a laptop outside of Pfsense and using the address cherry.seaoffate.net, we can try using the IP address of the Pfsense WAN port but it may not work (if the default server is set to cherry it may connect)&lt;br /&gt;
&lt;br /&gt;
===Additional Options===&lt;br /&gt;
&lt;br /&gt;
There are a few additional considerations that will make the servers run more reliably. The first is thing that needs to be done is to run the server in a screen so that there does not need to be a SSH session to be running. The following will start a screen called minecraft and will execute the start.sh command. &lt;br /&gt;
 screen -S minecraft ./start&lt;br /&gt;
To exit the minecraft screen and return to the main SSH type ctrl + a and then d, the minecraft screen can be reloaded with the command &lt;br /&gt;
 screen -r minecraft&lt;br /&gt;
The next thing that we will need to do is to have the minecraft server start whenever the host reboots. So we need to add a cron tab to the start.sh&lt;br /&gt;
 crontab -e&lt;br /&gt;
Select nano if asked then add the line &lt;br /&gt;
 @reboot screen -dmS minecraft /home/nigel/minecraft_server/start.sh&lt;br /&gt;
&lt;br /&gt;
The next thing is not a minecraft helper exactly but it will be useful as a reminder in the future. When a user logs on to the host the message of the day will be displayed to add simple notes to the message we can simply edit the motd with the command&lt;br /&gt;
 sudo nano /etc/motd&lt;br /&gt;
&lt;br /&gt;
===Adding a second Minecraft server Apple===&lt;br /&gt;
&lt;br /&gt;
Now that we have the basic setup with potential for multiple hosts we will need to create at least one more so that we can prove the proxy works as intended. The next server will be a different version with some mods. As soon as we start adding mods to a Minecraft world they will use more resources so we will need the next host to be a bit better specified.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 6 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 14GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 150GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Apple||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.35 ||&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1537</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1537"/>
		<updated>2026-05-12T18:00:52Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Adding a second Minecraft server Apple */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
The first Minecraft host needs to have enough resources to run the JVM and the server but as it just a vanilla server the specification does not need to be excessive. The table shows the highlights.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;br /&gt;
&lt;br /&gt;
===Velocity Installation===&lt;br /&gt;
&lt;br /&gt;
The Velocity server VM does not need to be especially high because all it needs to do is accept connections and forward them on to the relevant host and any associated functions like handle logon, bans and etc. Unlike the cherry host that we just setup the base specification from the Debian template needs to be cut down a bit and does not need a extra swap file or anything special.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 1 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 1GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Storage || 32GB ||  &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Vangueria ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.29 ||&lt;br /&gt;
|}&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
As there is no additions to the VM&#039;s specification there is no hardware to configure so we can get straight to the software installation. So the well known update/upgrade and the packages can be installed with&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless htop screen wget jq curl&lt;br /&gt;
Once the dependencies are installed, we create a dedicated application directory and use an automated script to identify the most recent build of Velocity 3.4.0. This ensures we are not relying on hardcoded links that may expire.&lt;br /&gt;
 mkdir ~/velocity &amp;amp;&amp;amp; cd ~/velocity&lt;br /&gt;
 export PROJECT=&amp;quot;velocity&amp;quot;&lt;br /&gt;
 export VERSION=&amp;quot;3.4.0-SNAPSHOT&amp;quot;&lt;br /&gt;
 export LATEST_BUILD=$(curl -s https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION} | jq &#039;.builds[-1]&#039;)&lt;br /&gt;
 wget -O ~/velocity/velocity.jar &amp;quot;https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION}/builds/${LATEST_BUILD}/downloads/${PROJECT}-${VERSION}-${LATEST_BUILD}.jar&amp;quot;&lt;br /&gt;
The initial boot of Velocity is performed to generate the necessary configuration files. We launch it with a 512MB heap size and then shut it down gracefully using the end command once the prompt appears.&lt;br /&gt;
 java -Xms512M -Xmx512M -jar velocity.jar&lt;br /&gt;
&lt;br /&gt;
====Proxy Configuration and Routing====&lt;br /&gt;
&lt;br /&gt;
The primary configuration for the proxy is handled within the velocity.toml file. This file dictates how the proxy listens for incoming traffic and how it maps domain names to internal IP addresses. We edit this file to ensure the proxy is listening on all interfaces and that it is using the modern forwarding protocol.&lt;br /&gt;
 nano ~/velocity/velocity.toml&lt;br /&gt;
Modify these specific lines:&lt;br /&gt;
* Bind Address: bind = &amp;quot;0.0.0.0:25565&amp;quot; (Allows it to hear traffic from pfSense).&lt;br /&gt;
* Forwarding Mode: player-info-forwarding-mode = &amp;quot;modern&amp;quot; (This is the most secure protocol for 2026).&lt;br /&gt;
* ping-passthrough should be set to ALL. This is to ensure the server list on the Minecraft client correctly displays the status and version of the backend servers&lt;br /&gt;
* Server List: Scroll down to the [servers] section:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[servers]&lt;br /&gt;
 cherry = &amp;quot;192.168.100.30:25565&amp;quot;&lt;br /&gt;
 apple = &amp;quot;192.168.100.35:25565&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 [servers]&lt;br /&gt;
 try = [&lt;br /&gt;
    &amp;quot;cherry&amp;quot;&lt;br /&gt;
 ]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Forced Hosts: This tells the proxy which server to pick based on the URL the player typed:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[forced-hosts]&lt;br /&gt;
 &amp;quot;cherry.seaoffate.net&amp;quot; = [&amp;quot;cherry&amp;quot;]&lt;br /&gt;
 &amp;quot;apple.seaoffate.net&amp;quot; = [&amp;quot;apple&amp;quot;]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Save and close the file. next we need a start.sh file for Velocity &lt;br /&gt;
 nano ~/velocity/start.sh&lt;br /&gt;
copy the following into the file&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Vangueria Proxy ---&amp;quot;&lt;br /&gt;
     java -Xms512M -Xmx512M \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar velocity.jar&lt;br /&gt;
     echo &amp;quot;--- Proxy stopped. Restarting in 5s ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
To make the script executable &lt;br /&gt;
 chmod +x ~/velocity/start.sh&lt;br /&gt;
At this point the since Vangueria is now set to Modern Forwarding, Cherry will reject all connections until it has the forwarding.secret. the secret can be obtained with the command&lt;br /&gt;
 cat ~/velocity/forwarding.secret&lt;br /&gt;
Copy the code to a safe location because we will need it to setup cherry (and apple). then we should be able to finally start the proxy with the start.sh&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now we move to cherry to setup it&#039;s ability to receive connections from Vangueria. &lt;br /&gt;
&lt;br /&gt;
====Configuring Cherry To Accept Proxied Connections====&lt;br /&gt;
&lt;br /&gt;
To complete the integration between the proxy and the backend, Cherry must be transitioned from a standalone Vanilla server to a &amp;quot;Proxy-Aware&amp;quot; host. Because Vanilla Minecraft does not natively support Velocity’s Modern Forwarding (the security handshake), we use the Fabric Loader as a lightweight wrapper. This allows us to install a bridge mod that validates the secret key without changing the gameplay experience.The transition of Cherry involves three main phases: installing the Fabric environment, adding the bridge mods, and configuring the security handshake to match Vangueria.&lt;br /&gt;
&lt;br /&gt;
First, we must stop the existing server and install the Fabric transition layer. This replaces the standard Mojang launcher with a version capable of loading the security bridge. We need to download the Fabric Installer and then Install Fabric for the 1.21.1 environment.&lt;br /&gt;
 cd ~/minecraft_server&lt;br /&gt;
 wget https://maven.fabricmc.net/net/fabricmc/fabric-installer/1.0.1/fabric-installer-1.0.1.jar&lt;br /&gt;
 java -jar fabric-installer-1.0.1.jar server -mcversion 1.21.1 -downloadMinecraft&lt;br /&gt;
Once complete, the installer will have created a new file named fabric-server-launch.jar. This is now the primary entry point for the server.&lt;br /&gt;
&lt;br /&gt;
To install the Security Bridge we require two specific components in the mods folder: the Fabric API (the library that allows mods to interact with the game engine) and FabricProxy-Lite (the specific mod that handles the Velocity secret key). It is vital to use version-matched JARs for 1.21.1 to ensure stability.&lt;br /&gt;
 mkdir -p ~/minecraft_server/mods&lt;br /&gt;
 wget -O ~/minecraft_server/mods/FabricProxy-Lite.jar https://github.com/OKTW-Network/FabricProxy-Lite/releases/download/v2.10.1/FabricProxy-Lite-2.10.1.jar&lt;br /&gt;
 wget -O ~/minecraft_server/mods/fabric-api.jar https://github.com/FabricMC/fabric-api/releases/download/0.116.11%2B1.21.1/fabric-api-0.116.11+1.21.1.jar&lt;br /&gt;
&lt;br /&gt;
To configure the handshake after placing the mods, we must run the server once to generate the configuration structure, then shut it down to inject the secret.&lt;br /&gt;
Update start.sh to point to fabric-server-launch.jar instead of server.jar&lt;br /&gt;
 sed -i &#039;s/server.jar/fabric-server-launch.jar/&#039; start.sh&lt;br /&gt;
Initial run to generate config (Type &#039;stop&#039; once the &#039;Done&#039; message appears)&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now, we create the configuration file and link it to Vangueria. This is where we ensure the backend only trusts traffic coming from our proxy.&lt;br /&gt;
 mkdir -p ~/minecraft_server/config&lt;br /&gt;
 nano ~/minecraft_server/config/FabricProxy-Lite.toml&lt;br /&gt;
Paste the following configuration into the file, ensuring the secret matches the one obtained from Vangueria:&lt;br /&gt;
 enabled = true&lt;br /&gt;
 hackOnlineMode = true&lt;br /&gt;
 secret = &amp;quot;PASTE_YOUR_VANGUERIA_SECRET_HERE&amp;quot;&lt;br /&gt;
The final step is to adjust the server.properties file. Because Vangueria handles the official Mojang authentication at the &amp;quot;front door,&amp;quot; the backend server must be set to offline mode to allow the proxy to pass the authenticated user data through.&lt;br /&gt;
 sed -i &#039;s/online-mode=true/online-mode=false/&#039; server.properties&lt;br /&gt;
With the configuration complete, the server should be launched inside a named screen session to ensure it remains active.&lt;br /&gt;
 screen -S minecraft ./start.sh&lt;br /&gt;
We should now change the Pfsense port forward rule to forward traffic to the 192.168.100.29 (IP address of Vangueria) and then connecting a client from a laptop outside of Pfsense and using the address cherry.seaoffate.net, we can try using the IP address of the Pfsense WAN port but it may not work (if the default server is set to cherry it may connect)&lt;br /&gt;
&lt;br /&gt;
===Additional Options===&lt;br /&gt;
&lt;br /&gt;
There are a few additional considerations that will make the servers run more reliably. The first is thing that needs to be done is to run the server in a screen so that there does not need to be a SSH session to be running. The following will start a screen called minecraft and will execute the start.sh command. &lt;br /&gt;
 screen -S minecraft ./start&lt;br /&gt;
To exit the minecraft screen and return to the main SSH type ctrl + a and then d, the minecraft screen can be reloaded with the command &lt;br /&gt;
 screen -r minecraft&lt;br /&gt;
The next thing that we will need to do is to have the minecraft server start whenever the host reboots. So we need to add a cron tab to the start.sh&lt;br /&gt;
 crontab -e&lt;br /&gt;
Select nano if asked then add the line &lt;br /&gt;
 @reboot screen -dmS minecraft /home/nigel/minecraft_server/start.sh&lt;br /&gt;
&lt;br /&gt;
The next thing is not a minecraft helper exactly but it will be useful as a reminder in the future. When a user logs on to the host the message of the day will be displayed to add simple notes to the message we can simply edit the motd with the command&lt;br /&gt;
 sudo nano /etc/motd&lt;br /&gt;
&lt;br /&gt;
===Adding a second Minecraft server Apple===&lt;br /&gt;
&lt;br /&gt;
Now that we have the basic setup with potential for multiple hosts we will need to create at least one more so that we can prove the proxy works as intended. The next server will be a different version with some mods. As soon as we start adding mods to a Minecraft world they will use more resources so we will need the next host to be a bit better specified.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 150GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Apple||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1536</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1536"/>
		<updated>2026-05-12T17:59:36Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Adding a second Minecraft server */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
The first Minecraft host needs to have enough resources to run the JVM and the server but as it just a vanilla server the specification does not need to be excessive. The table shows the highlights.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;br /&gt;
&lt;br /&gt;
===Velocity Installation===&lt;br /&gt;
&lt;br /&gt;
The Velocity server VM does not need to be especially high because all it needs to do is accept connections and forward them on to the relevant host and any associated functions like handle logon, bans and etc. Unlike the cherry host that we just setup the base specification from the Debian template needs to be cut down a bit and does not need a extra swap file or anything special.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 1 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 1GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Storage || 32GB ||  &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Vangueria ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.29 ||&lt;br /&gt;
|}&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
As there is no additions to the VM&#039;s specification there is no hardware to configure so we can get straight to the software installation. So the well known update/upgrade and the packages can be installed with&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless htop screen wget jq curl&lt;br /&gt;
Once the dependencies are installed, we create a dedicated application directory and use an automated script to identify the most recent build of Velocity 3.4.0. This ensures we are not relying on hardcoded links that may expire.&lt;br /&gt;
 mkdir ~/velocity &amp;amp;&amp;amp; cd ~/velocity&lt;br /&gt;
 export PROJECT=&amp;quot;velocity&amp;quot;&lt;br /&gt;
 export VERSION=&amp;quot;3.4.0-SNAPSHOT&amp;quot;&lt;br /&gt;
 export LATEST_BUILD=$(curl -s https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION} | jq &#039;.builds[-1]&#039;)&lt;br /&gt;
 wget -O ~/velocity/velocity.jar &amp;quot;https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION}/builds/${LATEST_BUILD}/downloads/${PROJECT}-${VERSION}-${LATEST_BUILD}.jar&amp;quot;&lt;br /&gt;
The initial boot of Velocity is performed to generate the necessary configuration files. We launch it with a 512MB heap size and then shut it down gracefully using the end command once the prompt appears.&lt;br /&gt;
 java -Xms512M -Xmx512M -jar velocity.jar&lt;br /&gt;
&lt;br /&gt;
====Proxy Configuration and Routing====&lt;br /&gt;
&lt;br /&gt;
The primary configuration for the proxy is handled within the velocity.toml file. This file dictates how the proxy listens for incoming traffic and how it maps domain names to internal IP addresses. We edit this file to ensure the proxy is listening on all interfaces and that it is using the modern forwarding protocol.&lt;br /&gt;
 nano ~/velocity/velocity.toml&lt;br /&gt;
Modify these specific lines:&lt;br /&gt;
* Bind Address: bind = &amp;quot;0.0.0.0:25565&amp;quot; (Allows it to hear traffic from pfSense).&lt;br /&gt;
* Forwarding Mode: player-info-forwarding-mode = &amp;quot;modern&amp;quot; (This is the most secure protocol for 2026).&lt;br /&gt;
* ping-passthrough should be set to ALL. This is to ensure the server list on the Minecraft client correctly displays the status and version of the backend servers&lt;br /&gt;
* Server List: Scroll down to the [servers] section:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[servers]&lt;br /&gt;
 cherry = &amp;quot;192.168.100.30:25565&amp;quot;&lt;br /&gt;
 apple = &amp;quot;192.168.100.35:25565&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 [servers]&lt;br /&gt;
 try = [&lt;br /&gt;
    &amp;quot;cherry&amp;quot;&lt;br /&gt;
 ]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Forced Hosts: This tells the proxy which server to pick based on the URL the player typed:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[forced-hosts]&lt;br /&gt;
 &amp;quot;cherry.seaoffate.net&amp;quot; = [&amp;quot;cherry&amp;quot;]&lt;br /&gt;
 &amp;quot;apple.seaoffate.net&amp;quot; = [&amp;quot;apple&amp;quot;]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Save and close the file. next we need a start.sh file for Velocity &lt;br /&gt;
 nano ~/velocity/start.sh&lt;br /&gt;
copy the following into the file&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Vangueria Proxy ---&amp;quot;&lt;br /&gt;
     java -Xms512M -Xmx512M \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar velocity.jar&lt;br /&gt;
     echo &amp;quot;--- Proxy stopped. Restarting in 5s ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
To make the script executable &lt;br /&gt;
 chmod +x ~/velocity/start.sh&lt;br /&gt;
At this point the since Vangueria is now set to Modern Forwarding, Cherry will reject all connections until it has the forwarding.secret. the secret can be obtained with the command&lt;br /&gt;
 cat ~/velocity/forwarding.secret&lt;br /&gt;
Copy the code to a safe location because we will need it to setup cherry (and apple). then we should be able to finally start the proxy with the start.sh&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now we move to cherry to setup it&#039;s ability to receive connections from Vangueria. &lt;br /&gt;
&lt;br /&gt;
====Configuring Cherry To Accept Proxied Connections====&lt;br /&gt;
&lt;br /&gt;
To complete the integration between the proxy and the backend, Cherry must be transitioned from a standalone Vanilla server to a &amp;quot;Proxy-Aware&amp;quot; host. Because Vanilla Minecraft does not natively support Velocity’s Modern Forwarding (the security handshake), we use the Fabric Loader as a lightweight wrapper. This allows us to install a bridge mod that validates the secret key without changing the gameplay experience.The transition of Cherry involves three main phases: installing the Fabric environment, adding the bridge mods, and configuring the security handshake to match Vangueria.&lt;br /&gt;
&lt;br /&gt;
First, we must stop the existing server and install the Fabric transition layer. This replaces the standard Mojang launcher with a version capable of loading the security bridge. We need to download the Fabric Installer and then Install Fabric for the 1.21.1 environment.&lt;br /&gt;
 cd ~/minecraft_server&lt;br /&gt;
 wget https://maven.fabricmc.net/net/fabricmc/fabric-installer/1.0.1/fabric-installer-1.0.1.jar&lt;br /&gt;
 java -jar fabric-installer-1.0.1.jar server -mcversion 1.21.1 -downloadMinecraft&lt;br /&gt;
Once complete, the installer will have created a new file named fabric-server-launch.jar. This is now the primary entry point for the server.&lt;br /&gt;
&lt;br /&gt;
To install the Security Bridge we require two specific components in the mods folder: the Fabric API (the library that allows mods to interact with the game engine) and FabricProxy-Lite (the specific mod that handles the Velocity secret key). It is vital to use version-matched JARs for 1.21.1 to ensure stability.&lt;br /&gt;
 mkdir -p ~/minecraft_server/mods&lt;br /&gt;
 wget -O ~/minecraft_server/mods/FabricProxy-Lite.jar https://github.com/OKTW-Network/FabricProxy-Lite/releases/download/v2.10.1/FabricProxy-Lite-2.10.1.jar&lt;br /&gt;
 wget -O ~/minecraft_server/mods/fabric-api.jar https://github.com/FabricMC/fabric-api/releases/download/0.116.11%2B1.21.1/fabric-api-0.116.11+1.21.1.jar&lt;br /&gt;
&lt;br /&gt;
To configure the handshake after placing the mods, we must run the server once to generate the configuration structure, then shut it down to inject the secret.&lt;br /&gt;
Update start.sh to point to fabric-server-launch.jar instead of server.jar&lt;br /&gt;
 sed -i &#039;s/server.jar/fabric-server-launch.jar/&#039; start.sh&lt;br /&gt;
Initial run to generate config (Type &#039;stop&#039; once the &#039;Done&#039; message appears)&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now, we create the configuration file and link it to Vangueria. This is where we ensure the backend only trusts traffic coming from our proxy.&lt;br /&gt;
 mkdir -p ~/minecraft_server/config&lt;br /&gt;
 nano ~/minecraft_server/config/FabricProxy-Lite.toml&lt;br /&gt;
Paste the following configuration into the file, ensuring the secret matches the one obtained from Vangueria:&lt;br /&gt;
 enabled = true&lt;br /&gt;
 hackOnlineMode = true&lt;br /&gt;
 secret = &amp;quot;PASTE_YOUR_VANGUERIA_SECRET_HERE&amp;quot;&lt;br /&gt;
The final step is to adjust the server.properties file. Because Vangueria handles the official Mojang authentication at the &amp;quot;front door,&amp;quot; the backend server must be set to offline mode to allow the proxy to pass the authenticated user data through.&lt;br /&gt;
 sed -i &#039;s/online-mode=true/online-mode=false/&#039; server.properties&lt;br /&gt;
With the configuration complete, the server should be launched inside a named screen session to ensure it remains active.&lt;br /&gt;
 screen -S minecraft ./start.sh&lt;br /&gt;
We should now change the Pfsense port forward rule to forward traffic to the 192.168.100.29 (IP address of Vangueria) and then connecting a client from a laptop outside of Pfsense and using the address cherry.seaoffate.net, we can try using the IP address of the Pfsense WAN port but it may not work (if the default server is set to cherry it may connect)&lt;br /&gt;
&lt;br /&gt;
===Additional Options===&lt;br /&gt;
&lt;br /&gt;
There are a few additional considerations that will make the servers run more reliably. The first is thing that needs to be done is to run the server in a screen so that there does not need to be a SSH session to be running. The following will start a screen called minecraft and will execute the start.sh command. &lt;br /&gt;
 screen -S minecraft ./start&lt;br /&gt;
To exit the minecraft screen and return to the main SSH type ctrl + a and then d, the minecraft screen can be reloaded with the command &lt;br /&gt;
 screen -r minecraft&lt;br /&gt;
The next thing that we will need to do is to have the minecraft server start whenever the host reboots. So we need to add a cron tab to the start.sh&lt;br /&gt;
 crontab -e&lt;br /&gt;
Select nano if asked then add the line &lt;br /&gt;
 @reboot screen -dmS minecraft /home/nigel/minecraft_server/start.sh&lt;br /&gt;
&lt;br /&gt;
The next thing is not a minecraft helper exactly but it will be useful as a reminder in the future. When a user logs on to the host the message of the day will be displayed to add simple notes to the message we can simply edit the motd with the command&lt;br /&gt;
 sudo nano /etc/motd&lt;br /&gt;
&lt;br /&gt;
===Adding a second Minecraft server Apple===&lt;br /&gt;
&lt;br /&gt;
Now that we have the basic setup with potential for multiple hosts we will need to create at least one more so that we can prove the proxy works as intended. The next server will be a different version with some mods. As soon as we start adding mods to a Minecraft world they will use more resources so we will need the next host to be a bit better specified.&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1535</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1535"/>
		<updated>2026-05-12T17:52:41Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Configuring Cherry To Accept Proxied Connections */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
The first Minecraft host needs to have enough resources to run the JVM and the server but as it just a vanilla server the specification does not need to be excessive. The table shows the highlights.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;br /&gt;
&lt;br /&gt;
===Velocity Installation===&lt;br /&gt;
&lt;br /&gt;
The Velocity server VM does not need to be especially high because all it needs to do is accept connections and forward them on to the relevant host and any associated functions like handle logon, bans and etc. Unlike the cherry host that we just setup the base specification from the Debian template needs to be cut down a bit and does not need a extra swap file or anything special.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 1 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 1GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Storage || 32GB ||  &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Vangueria ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.29 ||&lt;br /&gt;
|}&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
As there is no additions to the VM&#039;s specification there is no hardware to configure so we can get straight to the software installation. So the well known update/upgrade and the packages can be installed with&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless htop screen wget jq curl&lt;br /&gt;
Once the dependencies are installed, we create a dedicated application directory and use an automated script to identify the most recent build of Velocity 3.4.0. This ensures we are not relying on hardcoded links that may expire.&lt;br /&gt;
 mkdir ~/velocity &amp;amp;&amp;amp; cd ~/velocity&lt;br /&gt;
 export PROJECT=&amp;quot;velocity&amp;quot;&lt;br /&gt;
 export VERSION=&amp;quot;3.4.0-SNAPSHOT&amp;quot;&lt;br /&gt;
 export LATEST_BUILD=$(curl -s https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION} | jq &#039;.builds[-1]&#039;)&lt;br /&gt;
 wget -O ~/velocity/velocity.jar &amp;quot;https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION}/builds/${LATEST_BUILD}/downloads/${PROJECT}-${VERSION}-${LATEST_BUILD}.jar&amp;quot;&lt;br /&gt;
The initial boot of Velocity is performed to generate the necessary configuration files. We launch it with a 512MB heap size and then shut it down gracefully using the end command once the prompt appears.&lt;br /&gt;
 java -Xms512M -Xmx512M -jar velocity.jar&lt;br /&gt;
&lt;br /&gt;
====Proxy Configuration and Routing====&lt;br /&gt;
&lt;br /&gt;
The primary configuration for the proxy is handled within the velocity.toml file. This file dictates how the proxy listens for incoming traffic and how it maps domain names to internal IP addresses. We edit this file to ensure the proxy is listening on all interfaces and that it is using the modern forwarding protocol.&lt;br /&gt;
 nano ~/velocity/velocity.toml&lt;br /&gt;
Modify these specific lines:&lt;br /&gt;
* Bind Address: bind = &amp;quot;0.0.0.0:25565&amp;quot; (Allows it to hear traffic from pfSense).&lt;br /&gt;
* Forwarding Mode: player-info-forwarding-mode = &amp;quot;modern&amp;quot; (This is the most secure protocol for 2026).&lt;br /&gt;
* ping-passthrough should be set to ALL. This is to ensure the server list on the Minecraft client correctly displays the status and version of the backend servers&lt;br /&gt;
* Server List: Scroll down to the [servers] section:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[servers]&lt;br /&gt;
 cherry = &amp;quot;192.168.100.30:25565&amp;quot;&lt;br /&gt;
 apple = &amp;quot;192.168.100.35:25565&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 [servers]&lt;br /&gt;
 try = [&lt;br /&gt;
    &amp;quot;cherry&amp;quot;&lt;br /&gt;
 ]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Forced Hosts: This tells the proxy which server to pick based on the URL the player typed:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[forced-hosts]&lt;br /&gt;
 &amp;quot;cherry.seaoffate.net&amp;quot; = [&amp;quot;cherry&amp;quot;]&lt;br /&gt;
 &amp;quot;apple.seaoffate.net&amp;quot; = [&amp;quot;apple&amp;quot;]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Save and close the file. next we need a start.sh file for Velocity &lt;br /&gt;
 nano ~/velocity/start.sh&lt;br /&gt;
copy the following into the file&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Vangueria Proxy ---&amp;quot;&lt;br /&gt;
     java -Xms512M -Xmx512M \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar velocity.jar&lt;br /&gt;
     echo &amp;quot;--- Proxy stopped. Restarting in 5s ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
To make the script executable &lt;br /&gt;
 chmod +x ~/velocity/start.sh&lt;br /&gt;
At this point the since Vangueria is now set to Modern Forwarding, Cherry will reject all connections until it has the forwarding.secret. the secret can be obtained with the command&lt;br /&gt;
 cat ~/velocity/forwarding.secret&lt;br /&gt;
Copy the code to a safe location because we will need it to setup cherry (and apple). then we should be able to finally start the proxy with the start.sh&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now we move to cherry to setup it&#039;s ability to receive connections from Vangueria. &lt;br /&gt;
&lt;br /&gt;
====Configuring Cherry To Accept Proxied Connections====&lt;br /&gt;
&lt;br /&gt;
To complete the integration between the proxy and the backend, Cherry must be transitioned from a standalone Vanilla server to a &amp;quot;Proxy-Aware&amp;quot; host. Because Vanilla Minecraft does not natively support Velocity’s Modern Forwarding (the security handshake), we use the Fabric Loader as a lightweight wrapper. This allows us to install a bridge mod that validates the secret key without changing the gameplay experience.The transition of Cherry involves three main phases: installing the Fabric environment, adding the bridge mods, and configuring the security handshake to match Vangueria.&lt;br /&gt;
&lt;br /&gt;
First, we must stop the existing server and install the Fabric transition layer. This replaces the standard Mojang launcher with a version capable of loading the security bridge. We need to download the Fabric Installer and then Install Fabric for the 1.21.1 environment.&lt;br /&gt;
 cd ~/minecraft_server&lt;br /&gt;
 wget https://maven.fabricmc.net/net/fabricmc/fabric-installer/1.0.1/fabric-installer-1.0.1.jar&lt;br /&gt;
 java -jar fabric-installer-1.0.1.jar server -mcversion 1.21.1 -downloadMinecraft&lt;br /&gt;
Once complete, the installer will have created a new file named fabric-server-launch.jar. This is now the primary entry point for the server.&lt;br /&gt;
&lt;br /&gt;
To install the Security Bridge we require two specific components in the mods folder: the Fabric API (the library that allows mods to interact with the game engine) and FabricProxy-Lite (the specific mod that handles the Velocity secret key). It is vital to use version-matched JARs for 1.21.1 to ensure stability.&lt;br /&gt;
 mkdir -p ~/minecraft_server/mods&lt;br /&gt;
 wget -O ~/minecraft_server/mods/FabricProxy-Lite.jar https://github.com/OKTW-Network/FabricProxy-Lite/releases/download/v2.10.1/FabricProxy-Lite-2.10.1.jar&lt;br /&gt;
 wget -O ~/minecraft_server/mods/fabric-api.jar https://github.com/FabricMC/fabric-api/releases/download/0.116.11%2B1.21.1/fabric-api-0.116.11+1.21.1.jar&lt;br /&gt;
&lt;br /&gt;
To configure the handshake after placing the mods, we must run the server once to generate the configuration structure, then shut it down to inject the secret.&lt;br /&gt;
Update start.sh to point to fabric-server-launch.jar instead of server.jar&lt;br /&gt;
 sed -i &#039;s/server.jar/fabric-server-launch.jar/&#039; start.sh&lt;br /&gt;
Initial run to generate config (Type &#039;stop&#039; once the &#039;Done&#039; message appears)&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now, we create the configuration file and link it to Vangueria. This is where we ensure the backend only trusts traffic coming from our proxy.&lt;br /&gt;
 mkdir -p ~/minecraft_server/config&lt;br /&gt;
 nano ~/minecraft_server/config/FabricProxy-Lite.toml&lt;br /&gt;
Paste the following configuration into the file, ensuring the secret matches the one obtained from Vangueria:&lt;br /&gt;
 enabled = true&lt;br /&gt;
 hackOnlineMode = true&lt;br /&gt;
 secret = &amp;quot;PASTE_YOUR_VANGUERIA_SECRET_HERE&amp;quot;&lt;br /&gt;
The final step is to adjust the server.properties file. Because Vangueria handles the official Mojang authentication at the &amp;quot;front door,&amp;quot; the backend server must be set to offline mode to allow the proxy to pass the authenticated user data through.&lt;br /&gt;
 sed -i &#039;s/online-mode=true/online-mode=false/&#039; server.properties&lt;br /&gt;
With the configuration complete, the server should be launched inside a named screen session to ensure it remains active.&lt;br /&gt;
 screen -S minecraft ./start.sh&lt;br /&gt;
We should now change the Pfsense port forward rule to forward traffic to the 192.168.100.29 (IP address of Vangueria) and then connecting a client from a laptop outside of Pfsense and using the address cherry.seaoffate.net, we can try using the IP address of the Pfsense WAN port but it may not work (if the default server is set to cherry it may connect)&lt;br /&gt;
&lt;br /&gt;
===Additional Options===&lt;br /&gt;
&lt;br /&gt;
There are a few additional considerations that will make the servers run more reliably. The first is thing that needs to be done is to run the server in a screen so that there does not need to be a SSH session to be running. The following will start a screen called minecraft and will execute the start.sh command. &lt;br /&gt;
 screen -S minecraft ./start&lt;br /&gt;
To exit the minecraft screen and return to the main SSH type ctrl + a and then d, the minecraft screen can be reloaded with the command &lt;br /&gt;
 screen -r minecraft&lt;br /&gt;
The next thing that we will need to do is to have the minecraft server start whenever the host reboots. So we need to add a cron tab to the start.sh&lt;br /&gt;
 crontab -e&lt;br /&gt;
Select nano if asked then add the line &lt;br /&gt;
 @reboot screen -dmS minecraft /home/nigel/minecraft_server/start.sh&lt;br /&gt;
&lt;br /&gt;
The next thing is not a minecraft helper exactly but it will be useful as a reminder in the future. When a user logs on to the host the message of the day will be displayed to add simple notes to the message we can simply edit the motd with the command&lt;br /&gt;
 sudo nano /etc/motd&lt;br /&gt;
&lt;br /&gt;
===Adding a second Minecraft server===&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1534</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1534"/>
		<updated>2026-05-12T16:18:59Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Proxy Configuration and Routing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
The first Minecraft host needs to have enough resources to run the JVM and the server but as it just a vanilla server the specification does not need to be excessive. The table shows the highlights.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;br /&gt;
&lt;br /&gt;
===Velocity Installation===&lt;br /&gt;
&lt;br /&gt;
The Velocity server VM does not need to be especially high because all it needs to do is accept connections and forward them on to the relevant host and any associated functions like handle logon, bans and etc. Unlike the cherry host that we just setup the base specification from the Debian template needs to be cut down a bit and does not need a extra swap file or anything special.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 1 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 1GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Storage || 32GB ||  &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Vangueria ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.29 ||&lt;br /&gt;
|}&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
As there is no additions to the VM&#039;s specification there is no hardware to configure so we can get straight to the software installation. So the well known update/upgrade and the packages can be installed with&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless htop screen wget jq curl&lt;br /&gt;
Once the dependencies are installed, we create a dedicated application directory and use an automated script to identify the most recent build of Velocity 3.4.0. This ensures we are not relying on hardcoded links that may expire.&lt;br /&gt;
 mkdir ~/velocity &amp;amp;&amp;amp; cd ~/velocity&lt;br /&gt;
 export PROJECT=&amp;quot;velocity&amp;quot;&lt;br /&gt;
 export VERSION=&amp;quot;3.4.0-SNAPSHOT&amp;quot;&lt;br /&gt;
 export LATEST_BUILD=$(curl -s https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION} | jq &#039;.builds[-1]&#039;)&lt;br /&gt;
 wget -O ~/velocity/velocity.jar &amp;quot;https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION}/builds/${LATEST_BUILD}/downloads/${PROJECT}-${VERSION}-${LATEST_BUILD}.jar&amp;quot;&lt;br /&gt;
The initial boot of Velocity is performed to generate the necessary configuration files. We launch it with a 512MB heap size and then shut it down gracefully using the end command once the prompt appears.&lt;br /&gt;
 java -Xms512M -Xmx512M -jar velocity.jar&lt;br /&gt;
&lt;br /&gt;
====Proxy Configuration and Routing====&lt;br /&gt;
&lt;br /&gt;
The primary configuration for the proxy is handled within the velocity.toml file. This file dictates how the proxy listens for incoming traffic and how it maps domain names to internal IP addresses. We edit this file to ensure the proxy is listening on all interfaces and that it is using the modern forwarding protocol.&lt;br /&gt;
 nano ~/velocity/velocity.toml&lt;br /&gt;
Modify these specific lines:&lt;br /&gt;
* Bind Address: bind = &amp;quot;0.0.0.0:25565&amp;quot; (Allows it to hear traffic from pfSense).&lt;br /&gt;
* Forwarding Mode: player-info-forwarding-mode = &amp;quot;modern&amp;quot; (This is the most secure protocol for 2026).&lt;br /&gt;
* ping-passthrough should be set to ALL. This is to ensure the server list on the Minecraft client correctly displays the status and version of the backend servers&lt;br /&gt;
* Server List: Scroll down to the [servers] section:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[servers]&lt;br /&gt;
 cherry = &amp;quot;192.168.100.30:25565&amp;quot;&lt;br /&gt;
 apple = &amp;quot;192.168.100.35:25565&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 [servers]&lt;br /&gt;
 try = [&lt;br /&gt;
    &amp;quot;cherry&amp;quot;&lt;br /&gt;
 ]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Forced Hosts: This tells the proxy which server to pick based on the URL the player typed:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[forced-hosts]&lt;br /&gt;
 &amp;quot;cherry.seaoffate.net&amp;quot; = [&amp;quot;cherry&amp;quot;]&lt;br /&gt;
 &amp;quot;apple.seaoffate.net&amp;quot; = [&amp;quot;apple&amp;quot;]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Save and close the file. next we need a start.sh file for Velocity &lt;br /&gt;
 nano ~/velocity/start.sh&lt;br /&gt;
copy the following into the file&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Vangueria Proxy ---&amp;quot;&lt;br /&gt;
     java -Xms512M -Xmx512M \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar velocity.jar&lt;br /&gt;
     echo &amp;quot;--- Proxy stopped. Restarting in 5s ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
To make the script executable &lt;br /&gt;
 chmod +x ~/velocity/start.sh&lt;br /&gt;
At this point the since Vangueria is now set to Modern Forwarding, Cherry will reject all connections until it has the forwarding.secret. the secret can be obtained with the command&lt;br /&gt;
 cat ~/velocity/forwarding.secret&lt;br /&gt;
Copy the code to a safe location because we will need it to setup cherry (and apple). then we should be able to finally start the proxy with the start.sh&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now we move to cherry to setup it&#039;s ability to receive connections from Vangueria. &lt;br /&gt;
&lt;br /&gt;
====Configuring Cherry To Accept Proxied Connections====&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1533</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1533"/>
		<updated>2026-05-12T05:52:24Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Proxy Configuration and Routing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
The first Minecraft host needs to have enough resources to run the JVM and the server but as it just a vanilla server the specification does not need to be excessive. The table shows the highlights.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;br /&gt;
&lt;br /&gt;
===Velocity Installation===&lt;br /&gt;
&lt;br /&gt;
The Velocity server VM does not need to be especially high because all it needs to do is accept connections and forward them on to the relevant host and any associated functions like handle logon, bans and etc. Unlike the cherry host that we just setup the base specification from the Debian template needs to be cut down a bit and does not need a extra swap file or anything special.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 1 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 1GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Storage || 32GB ||  &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Vangueria ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.29 ||&lt;br /&gt;
|}&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
As there is no additions to the VM&#039;s specification there is no hardware to configure so we can get straight to the software installation. So the well known update/upgrade and the packages can be installed with&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless htop screen wget jq curl&lt;br /&gt;
Once the dependencies are installed, we create a dedicated application directory and use an automated script to identify the most recent build of Velocity 3.4.0. This ensures we are not relying on hardcoded links that may expire.&lt;br /&gt;
 mkdir ~/velocity &amp;amp;&amp;amp; cd ~/velocity&lt;br /&gt;
 export PROJECT=&amp;quot;velocity&amp;quot;&lt;br /&gt;
 export VERSION=&amp;quot;3.4.0-SNAPSHOT&amp;quot;&lt;br /&gt;
 export LATEST_BUILD=$(curl -s https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION} | jq &#039;.builds[-1]&#039;)&lt;br /&gt;
 wget -O ~/velocity/velocity.jar &amp;quot;https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION}/builds/${LATEST_BUILD}/downloads/${PROJECT}-${VERSION}-${LATEST_BUILD}.jar&amp;quot;&lt;br /&gt;
The initial boot of Velocity is performed to generate the necessary configuration files. We launch it with a 512MB heap size and then shut it down gracefully using the end command once the prompt appears.&lt;br /&gt;
 java -Xms512M -Xmx512M -jar velocity.jar&lt;br /&gt;
&lt;br /&gt;
====Proxy Configuration and Routing====&lt;br /&gt;
&lt;br /&gt;
The primary configuration for the proxy is handled within the velocity.toml file. This file dictates how the proxy listens for incoming traffic and how it maps domain names to internal IP addresses. We edit this file to ensure the proxy is listening on all interfaces and that it is using the modern forwarding protocol.&lt;br /&gt;
 nano ~/velocity/velocity.toml&lt;br /&gt;
Modify these specific lines:&lt;br /&gt;
* Bind Address: bind = &amp;quot;0.0.0.0:25565&amp;quot; (Allows it to hear traffic from pfSense).&lt;br /&gt;
* Forwarding Mode: player-info-forwarding-mode = &amp;quot;modern&amp;quot; (This is the most secure protocol for 2026).&lt;br /&gt;
* ping-passthrough should be set to ALL. This is to ensure the server list on the Minecraft client correctly displays the status and version of the backend servers&lt;br /&gt;
* Server List: Scroll down to the [servers] section:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[servers]&lt;br /&gt;
 cherry = &amp;quot;192.168.100.30:25565&amp;quot;&lt;br /&gt;
 apple = &amp;quot;192.168.100.35:25565&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 [servers]&lt;br /&gt;
 try = [&lt;br /&gt;
    &amp;quot;cherry&amp;quot;&lt;br /&gt;
 ]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Forced Hosts: This tells the proxy which server to pick based on the URL the player typed:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[forced-hosts]&lt;br /&gt;
 &amp;quot;cherry.seaoffate.net&amp;quot; = [&amp;quot;cherry&amp;quot;]&lt;br /&gt;
 &amp;quot;apple.seaoffate.net&amp;quot; = [&amp;quot;apple&amp;quot;]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Save and close the file. next we need a start.sh file for Velocity &lt;br /&gt;
 nano ~/velocity/start.sh&lt;br /&gt;
copy the following into the file&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Vangueria Proxy ---&amp;quot;&lt;br /&gt;
     java -Xms512M -Xmx512M \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar velocity.jar&lt;br /&gt;
     echo &amp;quot;--- Proxy stopped. Restarting in 5s ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
To make the script executable &lt;br /&gt;
 chmod +x ~/velocity/start.sh&lt;br /&gt;
At this point the since Vangueria is now set to Modern Forwarding, Cherry will reject all connections until it has the forwarding.secret. the secret can be obtained with the command&lt;br /&gt;
 cat ~/velocity/forwarding.secret&lt;br /&gt;
Copy the code to a safe location because we will need it to setup cherry (and apple). then we should be able to finally start the proxy with the start.sh&lt;br /&gt;
 ./start.sh&lt;br /&gt;
Now we move to cherry to setup it&#039;s ability to receive connections from Vangueria. On Vangueria&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1532</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1532"/>
		<updated>2026-05-12T05:28:33Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Velocity Installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
The first Minecraft host needs to have enough resources to run the JVM and the server but as it just a vanilla server the specification does not need to be excessive. The table shows the highlights.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;br /&gt;
&lt;br /&gt;
===Velocity Installation===&lt;br /&gt;
&lt;br /&gt;
The Velocity server VM does not need to be especially high because all it needs to do is accept connections and forward them on to the relevant host and any associated functions like handle logon, bans and etc. Unlike the cherry host that we just setup the base specification from the Debian template needs to be cut down a bit and does not need a extra swap file or anything special.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 1 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 1GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Storage || 32GB ||  &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Vangueria ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.29 ||&lt;br /&gt;
|}&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
As there is no additions to the VM&#039;s specification there is no hardware to configure so we can get straight to the software installation. So the well known update/upgrade and the packages can be installed with&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless htop screen wget jq curl&lt;br /&gt;
Once the dependencies are installed, we create a dedicated application directory and use an automated script to identify the most recent build of Velocity 3.4.0. This ensures we are not relying on hardcoded links that may expire.&lt;br /&gt;
 mkdir ~/velocity &amp;amp;&amp;amp; cd ~/velocity&lt;br /&gt;
 export PROJECT=&amp;quot;velocity&amp;quot;&lt;br /&gt;
 export VERSION=&amp;quot;3.4.0-SNAPSHOT&amp;quot;&lt;br /&gt;
 export LATEST_BUILD=$(curl -s https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION} | jq &#039;.builds[-1]&#039;)&lt;br /&gt;
 wget -O ~/velocity/velocity.jar &amp;quot;https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION}/builds/${LATEST_BUILD}/downloads/${PROJECT}-${VERSION}-${LATEST_BUILD}.jar&amp;quot;&lt;br /&gt;
The initial boot of Velocity is performed to generate the necessary configuration files. We launch it with a 512MB heap size and then shut it down gracefully using the end command once the prompt appears.&lt;br /&gt;
 java -Xms512M -Xmx512M -jar velocity.jar&lt;br /&gt;
&lt;br /&gt;
====Proxy Configuration and Routing====&lt;br /&gt;
&lt;br /&gt;
The primary configuration for the proxy is handled within the velocity.toml file. This file dictates how the proxy listens for incoming traffic and how it maps domain names to internal IP addresses. We edit this file to ensure the proxy is listening on all interfaces and that it is using the modern forwarding protocol.&lt;br /&gt;
 nano ~/velocity/velocity.toml&lt;br /&gt;
Modify these specific lines:&lt;br /&gt;
* Bind Address: bind = &amp;quot;0.0.0.0:25565&amp;quot; (Allows it to hear traffic from pfSense).&lt;br /&gt;
* Forwarding Mode: player-info-forwarding-mode = &amp;quot;modern&amp;quot; (This is the most secure protocol for 2026).&lt;br /&gt;
* ping-passthrough should be set to ALL. This is to ensure the server list on the Minecraft client correctly displays the status and version of the backend servers&lt;br /&gt;
* Server List: Scroll down to the [servers] section:&lt;br /&gt;
 [servers]&lt;br /&gt;
 cherry = &amp;quot;192.168.100.30:25565&amp;quot;&lt;br /&gt;
 apple = &amp;quot;192.168.100.35:25565&amp;quot;&lt;br /&gt;
* Forced Hosts: This tells the proxy which server to pick based on the URL the player typed:&lt;br /&gt;
 [forced-hosts]&lt;br /&gt;
 &amp;quot;cherry.seaoffate.net&amp;quot; = [&amp;quot;cherry&amp;quot;]&lt;br /&gt;
 &amp;quot;apple.seaoffate.net&amp;quot; = [&amp;quot;apple&amp;quot;]&lt;br /&gt;
Save and close the file. next we need a start.sh file for Velocity &lt;br /&gt;
 nano ~/velocity/start.sh&lt;br /&gt;
copy the following into the file&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Vangueria Proxy ---&amp;quot;&lt;br /&gt;
     java -Xms512M -Xmx512M \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar velocity.jar&lt;br /&gt;
     echo &amp;quot;--- Proxy stopped. Restarting in 5s ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1531</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1531"/>
		<updated>2026-05-12T04:52:49Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Velocity Installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
The first Minecraft host needs to have enough resources to run the JVM and the server but as it just a vanilla server the specification does not need to be excessive. The table shows the highlights.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;br /&gt;
&lt;br /&gt;
===Velocity Installation===&lt;br /&gt;
&lt;br /&gt;
The Velocity server VM does not need to be especially high because all it needs to do is accept connections and forward them on to the relevant host and any associated functions like handle logon, bans and etc. Unlike the cherry host that we just setup the base specification from the Debian template needs to be cut down a bit and does not need a extra swap file or anything special.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 1 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 1GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Storage || 32GB ||  &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Vangueria ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.29 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
As there is no additions to the VM&#039;s specification there is no hardware to configure so we can get straight to the software installation. So the well known update/upgrade&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;br /&gt;
then install the dependencies&lt;br /&gt;
 sudo apt install -y openjdk-25-jre-headless htop screen wget jq curl &lt;br /&gt;
Now we can start the main application installation. As with cherry we will setup the application in it&#039;s own directory within the user&#039;s home directory&lt;br /&gt;
 mkdir ~/velocity &amp;amp;&amp;amp; cd ~/velocity&lt;br /&gt;
We run the next block to download the latest build&lt;br /&gt;
 export PROJECT=&amp;quot;velocity&amp;quot;&lt;br /&gt;
 export VERSION=&amp;quot;3.4.0-SNAPSHOT&amp;quot;&lt;br /&gt;
 export LATEST_BUILD=$(curl -s https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION} | jq &#039;.builds[-1]&#039;)&lt;br /&gt;
 wget -O ~/velocity/velocity.jar &amp;quot;https://api.papermc.io/v2/projects/${PROJECT}/versions/${VERSION}/builds/${LATEST_BUILD}/downloads/${PROJECT}-${VERSION}-${LATEST_BUILD}.jar&amp;quot;&lt;br /&gt;
The initial Boot of velocity with a fresh 3.4.0 JAR, launch it. It will generate the configuration files and then wait for your input.&lt;br /&gt;
 cd ~/velocity&lt;br /&gt;
 java -Xms512M -Xmx512M -jar velocity.jar&lt;br /&gt;
Wait until you see the &amp;gt; prompt then type end and press Enter to shut it down gracefully. This ensures all config files, including the secret key, are written to the disk. &lt;br /&gt;
To configure Vangueria velocity to tell Vangueria (192.168.100.29) about Cherry (.30) and Apple (.35) edit the file velocity.toml &lt;br /&gt;
 nano ~/velocity/velocity.toml&lt;br /&gt;
Modify these specific lines:&lt;br /&gt;
* Bind Address: bind = &amp;quot;0.0.0.0:25565&amp;quot; (Allows it to hear traffic from pfSense).&lt;br /&gt;
* Forwarding Mode: player-info-forwarding-mode = &amp;quot;modern&amp;quot; (This is the most secure protocol for 2026).&lt;br /&gt;
* Server List: Scroll down to the [servers] section:&lt;br /&gt;
 [servers]&lt;br /&gt;
 cherry = &amp;quot;192.168.100.30:25565&amp;quot;&lt;br /&gt;
 apple = &amp;quot;192.168.100.35:25565&amp;quot;&lt;br /&gt;
* Forced Hosts: This tells the proxy which server to pick based on the URL the player typed:&lt;br /&gt;
 [forced-hosts]&lt;br /&gt;
    &amp;quot;cherry.seaoffate.net&amp;quot; = [&amp;quot;cherry&amp;quot;]&lt;br /&gt;
    &amp;quot;apple.seaoffate.net&amp;quot; = [&amp;quot;apple&amp;quot;]&lt;br /&gt;
* The &amp;quot;Secret Handshake&amp;quot;&lt;br /&gt;
This is the most important step for security. You need to get the secret key that Vangueria generated so your backend servers (Cherry/Apple) can trust it. &lt;br /&gt;
 cat ~/velocity/forwarding.secret&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1530</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1530"/>
		<updated>2026-05-12T01:23:27Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Velocity Installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
The first Minecraft host needs to have enough resources to run the JVM and the server but as it just a vanilla server the specification does not need to be excessive. The table shows the highlights.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;br /&gt;
&lt;br /&gt;
===Velocity Installation===&lt;br /&gt;
&lt;br /&gt;
The Velocity server VM does not need to be especially high because all it needs to do is accept connections and forward them on to the relevant host and any associated functions like handle logon, bans and etc. Unlike the cherry host that we just setup the base specification from the Debian template needs to be cut down a bit and does not need a extra swap file or anything special.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 1 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 1GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Storage || 32GB ||  &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Vangueria ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.29 ||&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1529</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1529"/>
		<updated>2026-05-12T01:07:11Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Velocity Installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
The first Minecraft host needs to have enough resources to run the JVM and the server but as it just a vanilla server the specification does not need to be excessive. The table shows the highlights.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;br /&gt;
&lt;br /&gt;
===Velocity Installation===&lt;br /&gt;
&lt;br /&gt;
The Velocity server VM does not need to be especially high because all it needs to do is accept connections and forward them on to the relevant host and any associated functions like handle logon, bans and etc. &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1528</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1528"/>
		<updated>2026-05-12T01:03:05Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* The First Minecraft Host Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
The first Minecraft host needs to have enough resources to run the JVM and the server but as it just a vanilla server the specification does not need to be excessive. The table shows the highlights.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;br /&gt;
&lt;br /&gt;
===Velocity Installation===&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1527</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1527"/>
		<updated>2026-05-12T00:58:55Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Velocity Installation===&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1526</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1526"/>
		<updated>2026-05-12T00:57:17Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* The First Minecraft Host Configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Hardware Configuration====&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1525</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1525"/>
		<updated>2026-05-12T00:56:03Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
====Testing====&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1524</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1524"/>
		<updated>2026-05-12T00:55:42Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Enable External Access */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
====Enable External Access====&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard.&lt;br /&gt;
&lt;br /&gt;
===Testing===&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1523</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1523"/>
		<updated>2026-05-12T00:55:19Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Software Installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
====Software Installation====&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
===Enable External Access===&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard. &lt;br /&gt;
&lt;br /&gt;
===Testing===&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1522</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1522"/>
		<updated>2026-05-12T00:52:11Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* The First Minecraft Host */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host Configuration===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;br /&gt;
Now that the hardware is setup and configured we can proceed to the software installation&lt;br /&gt;
&lt;br /&gt;
===Software Installation===&lt;br /&gt;
&lt;br /&gt;
The software installation consists of updates, install the JVM and then install the Minecraft server. So to start as we do on most hosts with updates&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt upgrade&lt;br /&gt;
Install Necessary Utilities:&lt;br /&gt;
 sudo apt install htop screen wget curl -y&lt;br /&gt;
Install Java 25:&lt;br /&gt;
 sudo apt install openjdk-25-jre-headless -y&lt;br /&gt;
Verify Java Installation (Ensure it reports OpenJDK 25)&lt;br /&gt;
 java -version &lt;br /&gt;
Now we install the Minecraft server &lt;br /&gt;
&lt;br /&gt;
Create the Server Directory:&lt;br /&gt;
 mkdir ~/minecraft_server &amp;amp;&amp;amp; cd ~/minecraft_server&lt;br /&gt;
Download the Server Software: &lt;br /&gt;
 wget -O server.jar [https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar](https://piston-data.mojang.com/v1/objects/97ccd4c0ed3f81bbb7bfacddd1090b0c56f9bc51/server.jar)&lt;br /&gt;
Assuming the file downloaded we need an initial run to generate the file:&lt;br /&gt;
 java -Xms1G -Xmx1G -jar server.jar nogui&lt;br /&gt;
When the file is first created it will not run until we Accept the EULA with the command:&lt;br /&gt;
 sed -i &#039;s/eula=false/eula=true/&#039; eula.txt&lt;br /&gt;
We can create the Start Script:&lt;br /&gt;
 nano start.sh&lt;br /&gt;
Paste in the following&lt;br /&gt;
&amp;lt;nowiki&amp;gt; #!/bin/bash&lt;br /&gt;
 while true&lt;br /&gt;
 do&lt;br /&gt;
     echo &amp;quot;--- Starting Minecraft Server ---&amp;quot;&lt;br /&gt;
     java -Xms3G -Xmx3G \&lt;br /&gt;
          --enable-native-access=ALL-UNNAMED \&lt;br /&gt;
          -XX:+UseG1GC \&lt;br /&gt;
          -XX:MaxGCPauseMillis=200 \&lt;br /&gt;
          -XX:+UnlockExperimentalVMOptions \&lt;br /&gt;
          -XX:+DisableExplicitGC \&lt;br /&gt;
          -XX:+AlwaysPreTouch \&lt;br /&gt;
          -jar server.jar nogui&lt;br /&gt;
     echo &amp;quot;--- Server stopped. Restarting in 5 seconds (Ctrl+C to cancel) ---&amp;quot;&lt;br /&gt;
     sleep 5&lt;br /&gt;
 done&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Set the script to execute with &lt;br /&gt;
 chmod +x start.sh&lt;br /&gt;
We can start the server with &lt;br /&gt;
 ./start.sh&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; we can type the command stop in the terminal and the server will save the world and stop it for 5 seconds during the 5 seconds, if we type ctrl+c it will end the script or if we just leave it the server will restart.&lt;br /&gt;
&lt;br /&gt;
===Enable External Access===&lt;br /&gt;
&lt;br /&gt;
We will need to access the server from outside world so we should forward the Minecraft port 25565 to the IP address of cherry. To make the port forward rules in Pfsense easier to understand we add an alias for cherry&#039;s IP address and a port alias for 25565. We add a port forward rule to Pfsense that says  source IP 192.168.0.0/16 and any port, destination this firewall (self) Destination port Minecraft_standard, redirect IP_cherry port Minecraft_standard. &lt;br /&gt;
&lt;br /&gt;
===Testing===&lt;br /&gt;
&lt;br /&gt;
With this configuration loading a Minecraft client and setting the destination server to the WAN port IP address it will connect to the cherry host. &lt;br /&gt;
&lt;br /&gt;
As part of the wider LAN setup we added a Adguard LXC to manage DNS. Part of the Adguard configuration was made to avoid the hairpin network access so a DNS redirect was made to forward *.seaoffate.net to Pfsense WAN and as the default domain name was set to seaoffate.net. So now when we have a destination of cherry Adguard will translate the hostname to cherry.seaoffate.net and redirect it to Pfsense, Pfsense will then forward to the relevant server. If that does not work as expected the next test would be to set the destination to cherry.seaoffate.net which should be redirected by Adguard.&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1521</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1521"/>
		<updated>2026-05-11T23:02:42Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* The First Minecraft Host */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The Cherry host was created as a clone of the Debian template and then the basic specifications were improved so we will need to configure these extra items in the OS. First we need to identify the harddrive to use as the swap file &lt;br /&gt;
 lsblk&lt;br /&gt;
The result is likely to show that the disk is likely to be /dev/sdb so we can set the swap space and enable it with&lt;br /&gt;
 sudo mkswap /dev/sdb&lt;br /&gt;
 sudo swapon /dev/sdb&lt;br /&gt;
To make the swap file persistent we edit the fstab &lt;br /&gt;
 sudo nano /etc/fstab&lt;br /&gt;
Add the line: &lt;br /&gt;
 /dev/sdb none swap sw 0 0&lt;br /&gt;
and remove or comment out the line that refers to&lt;br /&gt;
 /dev/sda3&lt;br /&gt;
Before the storage sda main partition can be expanded to the full 96GB we have to remove the swap that is in the way so disable the existing swap with &lt;br /&gt;
 sudo swapoff /dev/sda3&lt;br /&gt;
Open the disk utility to modify sda&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the swap partition with the option d, then type 3 to delete partition 3, then w to save and exit. The next thing to do is expand the Primary Root Partition so open fdisk again:&lt;br /&gt;
 sudo fdisk /dev/sda&lt;br /&gt;
Delete the root partition:&lt;br /&gt;
* Type d (Delete) &lt;br /&gt;
* Type 2 (this only deletes the table entry, not the data). &lt;br /&gt;
* Type n (Create a new partition)&lt;br /&gt;
* Type p (Primary Partition)&lt;br /&gt;
* Type 2 (For Partition number 2)&lt;br /&gt;
* Type enter (Use default values for start sector)&lt;br /&gt;
* Type enter (Use default values for end sectors to fill the 96GB)&lt;br /&gt;
* CRITICAL: When asked if you want to remove the signature, type N.&lt;br /&gt;
* Type w (Save and exit)&lt;br /&gt;
To finalize Storage reboot to refresh the kernel partition table:&lt;br /&gt;
 sudo systemctl reboot&lt;br /&gt;
When the VM reboots expand the filesystem into the new space:&lt;br /&gt;
 sudo resize2fs /dev/sda2&lt;br /&gt;
We can verify the new swap and new sda size with &lt;br /&gt;
 df -h&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1520</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1520"/>
		<updated>2026-05-11T22:21:44Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* The First Minecraft Host */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value !! Notes&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB ||&lt;br /&gt;
|-&lt;br /&gt;
|Swap || 16gb || Additional disk allocated from Lexar SSD &lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB || Initially set at 32gb &lt;br /&gt;
|-&lt;br /&gt;
|Base OS || Debian 13.3 || Server version&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry ||&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30 ||&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1519</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1519"/>
		<updated>2026-05-11T22:11:54Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* The First Minecraft Host */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB&lt;br /&gt;
|-&lt;br /&gt;
| Lexar Swap || 16gb&lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB&lt;br /&gt;
|-&lt;br /&gt;
| Base OS || Debian 13.3&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1518</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1518"/>
		<updated>2026-05-11T22:10:48Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* The First Minecraft Host */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! emoji !! {| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ &lt;br /&gt;
|-&lt;br /&gt;
! Item !! Value&lt;br /&gt;
|-&lt;br /&gt;
|CPU || 2&lt;br /&gt;
|-&lt;br /&gt;
|RAM || 4GB&lt;br /&gt;
|-&lt;br /&gt;
| Lexar Swap || 16gb&lt;br /&gt;
|-&lt;br /&gt;
|Storage || 96GB&lt;br /&gt;
|-&lt;br /&gt;
| Base OS || Debian 13.3&lt;br /&gt;
|-&lt;br /&gt;
|Hostname || Cherry&lt;br /&gt;
|-&lt;br /&gt;
|IP Address || 192.168.100.30&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1517</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1517"/>
		<updated>2026-05-11T21:59:11Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
The installation will be in some distinct stages to enable each step to be proved to be working before proceeding to the next stage. First we setup a simple vanilla Minecraft server and set the firewall to port forward to it directly. Once that is proven to be working we will setup a Velocity server that will receive all 25565 traffic and forward it to the working Minecraft host. The next phase after the first host is getting traffic forwarded is to setup a second host and make sure velocity can forward to each, included in this step will be hardening the Velocity server with whatever security measures that it has available. When we are sure that Velocity is working properly we can work on the remote access stage, where we use TCPShield to proxy the service and have Cloudflare DNS only names setup with cherry.seaoffate.net and apple.seaoffate.net etc. From this point forward any new Minecraft servers will simply follow the same setup procedure.&lt;br /&gt;
&lt;br /&gt;
===The First Minecraft Host===&lt;br /&gt;
&lt;br /&gt;
The initial host will&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1516</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1516"/>
		<updated>2026-05-11T21:19:58Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;&#039;. The general setup will be to have a Velocity server in front several Minecraft host &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1515</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1515"/>
		<updated>2026-05-11T21:19:15Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the [[Home Lab]]. The general setup will be to have a Velocity server in front several Minecraft host [[Virtual Machines]]. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1514</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1514"/>
		<updated>2026-05-11T21:17:45Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the [[Home lab]]. The general setup will be to have a Velocity server in front several Minecraft host [[Virtual Machines]]. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1513</id>
		<title>Minecraft</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Minecraft&amp;diff=1513"/>
		<updated>2026-05-11T21:15:12Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: Created page with &amp;quot;==Introduction==  We are to have some Minecraft servers on the Homelab. The general setup will be to have a Velocity server in front several Minecraft host VMs. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We are to have some Minecraft servers on the [[Homelab]]. The general setup will be to have a Velocity server in front several Minecraft host VMs. Velocity works in a similar way to a Nginx reverse proxy whereby Pfsense forwards all Minecraft traffic to the Velocity server including the SNI and Velocity redirects traffic to the required hostname based on the DNS name. Cloudflare does not reverse proxy Minecraft traffic on the free tier and as we do not want to have to deal with random bots from the east so we will not leave the port open on the edge or Pfsense to random bots with port scanners. So we will use grey cloud at Cloudflare but DNS will point to a service like TCPShield and our firewalls only accept Minecraft traffic from their IP addresses and Velocity will only accept named servers and drop any unknown DNS names.&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Proxmox_Server&amp;diff=1512</id>
		<title>Proxmox Server</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Proxmox_Server&amp;diff=1512"/>
		<updated>2026-05-01T07:33:52Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* 🥝 Kiwi Host: Technical Manual &amp;amp; Build Log */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==📋Introduction==&lt;br /&gt;
&lt;br /&gt;
This is the server that will sit under my desk until I move house. It has the hostname Pear and will be the beginning of the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;. There is also now a new smaller and less powerful server with the hostname Kiwi.&lt;br /&gt;
&lt;br /&gt;
==🥝[[Create Virtual Machine from a template]]==&lt;br /&gt;
&lt;br /&gt;
it is possible to create a new VM based on a fixed template. The two possibilities are a full clone or a linked clone. the linked clone is the preferred as it should need less storage but the full clone would be completely independent of the template so it will use more storage and take longer to create.We can go down that rabbit hole when we look ant Ansible in a big way. For now just understand that we can call a new vm  using the  qm clone command. the will be more details to follow.&lt;br /&gt;
&lt;br /&gt;
==Orchard (Pear)==&lt;br /&gt;
The first host has Proxmox installed with the following specification&lt;br /&gt;
&lt;br /&gt;
===🛠️Hardware Specification===&lt;br /&gt;
&lt;br /&gt;
The Main components were purchased in 2024 as follows&lt;br /&gt;
&lt;br /&gt;
* The Cpu is AMD Ryzen 9 5950X Processor (16Cores/32Threads, 105W TDP, Socket AM4, 72MB Cache, Up to 4.9 GHz Max Boost, no cooler) £369.98&lt;br /&gt;
* The cooler is Noctua NH-D15, Premium CPU Cooler with 2x NF-A15 PWM 140mm Fans (Brown) £99.95&lt;br /&gt;
* Mainboard is Gigabyte B550M AORUS ELITE Motherboard - Supports AMD Ryzen 5000 Series AM4 CPUs, 5+3 Phases Pure Digital VRM, up to 4733MHz DDR4 (OC), 2xPCIe 3.0 M.2, GbE LAN, USB 3.2 Gen1 £103.48&lt;br /&gt;
* 128gb Ram is configured as two sets of CORSAIR VENGEANCE LPX DDR4 RAM 64GB (2x32GB) 3200MHz CL16-20-20-38 1.35V (CMK64GX4M2E3200C16) £112.20 for one set&lt;br /&gt;
* GPU is a Gigabyte Geforce RTX 5060 TI with 16 GB Ram&lt;br /&gt;
* Power supply is Corsair RM750x 80 Plus Gold Fully Modular ATX 750 Watt Power Supply £109.00&lt;br /&gt;
* The case is Fractal Design Node 804 - Black - Compact Computer Case - mATX - High Airflow - Modular interior - 3x Fractal Design Silent R2 120mm Fans Included - Water-cooling ready - USB 3.0 -Window Side Panel £99.95 &lt;br /&gt;
* SSD is Crucial P3 Plus SSD 4TB M.2 NVMe PCIe Gen4 Internal SSD, Up to 4800MB/s, Laptop &amp;amp; Desktop (PC) Compatible, Solid State Drive - CT4000P3PSSD801 £189.99 and £159.99&lt;br /&gt;
* Three 16 TB Seagate Ironwolf NAS drives make up the hard disk storage at a cost of £179.94 each total £ 539.82.&lt;br /&gt;
* One cheap 1 TB SATA SSD currently set as a L2ARC but may reconfigure as a sacrificial drive for the high wear VMs if it looks like it is not getting many hits as L2ARC &#039;&#039;&#039;Update &#039;&#039;&#039; no longer used as L2ARC and formmated to a zpool fastpool.&lt;br /&gt;
&lt;br /&gt;
===Configuration===&lt;br /&gt;
&lt;br /&gt;
====🌐Network Access====&lt;br /&gt;
&lt;br /&gt;
The IP Address and port of the host is 192.168.0.110:8006. I have my virgin media router forwarding all incoming traffic to 192.168.0.125 so it will go directly to the Pfsense firewall. All of the terminals can also send traffic to the WAN port of Pfsense. &#039;&#039;&#039;Edit&#039;&#039;&#039; with the change to Vodaphone the network address changed to 192.168.1.0/24 so Proxmox console is now 192.168.1.111:8006 and the WAN port of Pfsense is 192.168.1.125. a further change was to only forward those ports that are actually needed to Pfsense because the new ISP router has better options than the really old Virgin media one ( to be fair if i had stayed with Virgin i would have got a newer router). More &#039;&#039;&#039;[[Network Configuration]]&#039;&#039;&#039; details.&lt;br /&gt;
&lt;br /&gt;
====💾Storage====&lt;br /&gt;
&lt;br /&gt;
The main storage is the three 16TB hard drives configure into ZFS z1 so that they have one redundant disk. As one disk is redundant, obviously, it has 32TB of storage available.&lt;br /&gt;
&lt;br /&gt;
I couldn&#039;t get PCI passthrough to work reliably without significant effort and some expense so I set up ZFS on Proxmox itself or more precisely on the Debian Linux that Proxmox resides on. Unfortunately, that means that I have to do any config on the CLI. I may write some scripts to perform some of the admin tasks or more likely setup a Nginx container to automate as much of it as possible. For the time being some useful ZFS commands can be found &#039;&#039;&#039;[[ZFS Commands |here]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==🥝 Grove (Kiwi) : Technical Manual &amp;amp; Build Log==&lt;br /&gt;
&lt;br /&gt;
Kiwi is the secondary Proxmox host in the Home Lab, housed in a Fractal Design ITX chassis. While less powerful than the primary host (Pear), it serves as a high-capacity storage node and 2.5G data target.&lt;br /&gt;
&lt;br /&gt;
=== Hardware Specification ===&lt;br /&gt;
&lt;br /&gt;
* CPU: AMD Ryzen 5 with Stock Wraith Cooler.&lt;br /&gt;
* RAM: 64GB (2x32GB Crucial DDR4), maxing out the two available slots.&lt;br /&gt;
* System Drive: 2TB Samsung 990 Pro NVMe (Firmware verified: 5B2QJXD7).&lt;br /&gt;
* Storage Pool: 3x 14TB Seagate IronWolf Pro HDDs (ZFS RAIDZ1, 28TB usable).&lt;br /&gt;
* Network: Onboard 2.5 Gbps Wired NIC (nic0) + Built-in Wi-Fi (wlp5s0).&lt;br /&gt;
* GPU: Legacy Nvidia GPU (Required for POST and initial installation). The Mainboard has 4 SATA ports on board. Three of them have 14 TB Ironwolf pro drives to be formatted as a ZFS array with Z! so will give 28TB of usable storage with one disk of redundancy&lt;br /&gt;
&lt;br /&gt;
===Proxmox Installation===&lt;br /&gt;
&lt;br /&gt;
It is assumed that the Proxmox installer has been downloaded from their website and the iso has been copied on to a USB stick and made bootable with Rufus or some other similar. If the reader doesn&#039;t know how to make a USB installer from an ISO try typing &amp;quot;How do I make a USB stick into a proxmox installer&amp;quot; in to a browser. there will be loads of guides on how to use Rufus. When a bootable USB stick with Proxmox installer on it has been created insert in to one of the USB slots along with a keyboard, mouse and screen. Please note the keyboard mouse and screen will only be needed for the installation, once Proxmox is installed it is unlikely that these will ever be used again because virtually all administration is performed on a web GUI. &lt;br /&gt;
&lt;br /&gt;
====BIOS settings for Hypervisors (including Proxmox)====&lt;br /&gt;
&lt;br /&gt;
Generally most BIOS can be left at defaults and a PC as a PC will work well enough, maybe the boot priority may need to be changed from a HDD to a SSD but even that is unlikely. It is possible to optimise lots of things in BIOS and for some people that is an option but it is also easy to make mistakes that either stop the machine from working or making the machine unstable so for most people, most of the time, it is better to leave BIOS alone. A big exception is when a hypervisor is to be install because a few options that are off by default need to be set for Virtualisation to work properly. The main things to set are:-&lt;br /&gt;
* SVM Mode (AMD-V): &#039;&#039;&#039;Must be Enabled.&#039;&#039;&#039; This is what allows Proxmox to run VMs. Without it virtualisation will fail with most or possibly all hypervisors&lt;br /&gt;
* IOMMU: Set to Enabled. This is vital if you ever want to &amp;quot;pass through&amp;quot; a SATA controller or GPU directly to a VM. while not vital for the virtualisation itself most hypervisors have this enabled.&lt;br /&gt;
* Power Supply Idle Control: If you find the server randomly freezes when idle, set this to &amp;quot;Typical Current Idle&amp;quot;. Ryzen chips sometimes drop voltage too low for some power supplies when idling, causing a crash. Again not vital but a &amp;quot;nice to have&amp;quot; if possible in the BIOS.&lt;br /&gt;
* Boot options: The SSD should be at the top. It is better to set the USB at the bottom so that if a USB is left in the machine and it is rebooted it doesn&#039;t try to boot from the USB.&lt;br /&gt;
Once the BIOS option are set save the settings and quit. The computer will shutdown and restart, while it is restarting keep pressing the delete key or the F12 key to bring up the boot options (it is usually delete key but it should also display the options briefly on the screen as it starts). &lt;br /&gt;
&lt;br /&gt;
====GPU Considerations====&lt;br /&gt;
&lt;br /&gt;
The Proxmox installation is a little bit more tricky than is standard for the majority of computers in that this has an old GPU that the installer does not recognise. A GPU is required so that the machine will pass POST but is not really need or used by the Proxmox guests so is generally of little benefit for the overall Proxmox day to day running. A lot of Hypervisor hosts have the cheapest and lowest power GPUs installed just enough to POST but no more than that. The reason that GPU is of low priorty for most hypervisors hosts is that they are generally run headless, that is without a monitor attached, all interations with the host is through a dedicated application like Citrix XEN, or more likely through a web browser like Proxmox. Web based GUIs are popular because it is a lot easier and lighter processor load to have a webserver attached than it is to design a whole application. Kiwi has an old Nvidia GPU that works in that it provides a display but that is about it. Unfortunately, it does give some problems for the installer as it is so old but therea re steps to overcome that as will be detailed below. We may add a bigger and better GPU at a later date but for the foreseeable future that is in the realms of an upgrade for later and dependant on inheriting a GPU from another box.&lt;br /&gt;
&lt;br /&gt;
====Proxmox Installer problems (The Kiwi exceptions)====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As stated earlier the Proxmox installer does not work with the GPU. This is shown in that the machine boots and loads the first screen of the installer with welcome to.. but when the first option is tried it starts to load then freezes at the loading Nvidia drivers or some such thing(cant remember exactly what it says). so to fix that issue we need to restart the host and when we get to the welcome screen again we highlight &amp;quot;Install Proxmox VE (Graphical)&amp;quot; but &#039;&#039;&#039;do not press Enter&#039;&#039;&#039; instead we press &amp;quot;e&amp;quot; so a black screen with GNU GRUB appears. Edit the line&lt;br /&gt;
 linux /boot/linux26 ro ramdisk_size=16777216 rw quiet splash=silent&lt;br /&gt;
so it reads &lt;br /&gt;
 linux /boot/linux26 ro ramdisk_size=16777216 rw nomodeset&lt;br /&gt;
* By removing the quiet splash=silent we force the installer to show every single line of code as it loads. If it freezes again, we see the exact driver name where it stopped (e.g., sata_nv or i915).&lt;br /&gt;
* Adding nomodeset: This is the &amp;quot;magic bullet&amp;quot; for the nvidiafb hang. It tells the kernel not to touch the video drivers until the system is fully loaded. It is most likely where the installer hangs. As we should see every line of the execution of the installer if we have a different driver issue we should still see it.&lt;br /&gt;
To save the changes press ctrl+x or maybe F10. The GNU Grub screen will close and the graphical installer will continue until it gets to the &amp;quot;end user license agreement (EULA) screen. For anyone else reading this, If  the installer freezes again before it gets to the EULA screen the error will most likely be in the last laine of text displayed. The most likely error will be a conflict between Debian kernel and Advanced Configuration and Power Interface (ACPI) in which case restart and press the &amp;quot;e&amp;quot; to get to the Grub config and edit the same line &lt;br /&gt;
 linux /boot/linux26 ro ramdisk_size=16777216 rw nomodeset&lt;br /&gt;
so that it now has noapic added. note that this is just for the installer not the Proxmox application. &lt;br /&gt;
 linux /boot/linux26 ro ramdisk_size=16777216 rw nomodeset noapic&lt;br /&gt;
After modifying that line press ctrl+x or F10 to save and proceed. if it stalls again you will need to look for the exact error in the last line or last few lines that the installer performed or any line that starts or ends with failed.&lt;br /&gt;
&lt;br /&gt;
====Proxmox installer continued====&lt;br /&gt;
&lt;br /&gt;
After the earlier problems we should have got to the ELUA screen so press &amp;quot;I agree&amp;quot; button to continue. The next screen will be about choosing hard drives. Kiwi has a single SSD and three Ironwolf Pro 14 TB HDDs. Obviously, we will not install the OS onto a HDD or even all three HDDs as it would be too slow and as the SSD is fast we will choose that as the Target Harddisk. with the SSD selected click on options button.&lt;br /&gt;
* select zfs (RAID0) &lt;br /&gt;
* select samsung SSD as hardisk 0&lt;br /&gt;
* select Do not use for harddisk 1&lt;br /&gt;
* select Do not use for harddisk 2&lt;br /&gt;
* select Do not use for harddisk 3&lt;br /&gt;
ZFS is the best choice as it has native compression, Bitrot detection but not really protection because there is only one drive so nowhere to restore any corrupt data from. ZFS also has good snapshot capability. Ext4 / XFS are &amp;quot;set it and forget it&amp;quot; options. They use almost zero RAM, but they offer no protection against data corruption and have very basic snapshotting capabilities (via LVM).  Btrfs is similar to ZFS but generally considered less stable and has a lower feature set. The HDDs will not be used during the installation of Proxmox because it is easier to set them up from within the Proxmox web GUI or CLI.so the do not use is the best option for now &#039;&#039;&#039;note&#039;&#039;&#039; before we exit the Harddisk Options we need to check that the &#039;&#039;&#039;ashift&#039;&#039;&#039; is set to 12 so that the data blocks align with the physical page size of the Samsung 990 Pro&#039;s NAND, ensuring maximum speed, so select Advanced Options button next to Disk setup. Choose&lt;br /&gt;
* ashift is 12&lt;br /&gt;
* compress is on&lt;br /&gt;
* checksum is on&lt;br /&gt;
* copies is 1. Since this is a single-disk ZFS RAID0, copies=1 is the standard. If it is set it to 2, it would store every block twice on the same physical SSD. While that would allow ZFS to repair bitrot, it would effectively cut the 2TB SSD down to 1TB and halve the write speeds. With a 990 Pro, standard checksums and a good backup strategy are much more efficient.&lt;br /&gt;
* ARC max size 6422 Since there are only have two RAM slots and we are capped at 64GB, we need to be very intentional about how we carve up Kiwi RAM. having said that it is only a Maximum not a set size and zfs does not have to use all of it&#039;s maximum&lt;br /&gt;
* hdsize is set to maximum ( the + button will only allow it to be the size of the harddisk so click it until it stops going up)&lt;br /&gt;
Check the settings and when all looks correct click next for the regional settings&lt;br /&gt;
* Country United Kingdom&lt;br /&gt;
* Timezone Europe/London (or UTC if preferred)&lt;br /&gt;
* Keyboard Layout United Kingdom&lt;br /&gt;
Then next to set password and email address screen. Set a strong password that you can remember for the administration of the host. If the password is lost it will be almost impossible to recover it so do not forget it. Also it will be the hackers dream to get hold of the Proxmox host&#039;s password in that all of the rest of the security is mainly built on top of the administration of the host. If a host in a cluster is compromised it is quite likely that the whole cluster is compromised. The email address is so Proxmox can send promotional or updates but in general they don&#039;t flood their users with spam so it is no problem adding in a real email address. When done Click next to se the Management Network configuration screen.&lt;br /&gt;
&lt;br /&gt;
The Management Network Configuration will determine where the WebGUI will be presented from. Kiwi has two NICs, one is the 2.5 GB p/s wired NIC and the other is the wireless NIC. by default it is likely to be the wired NIC that is going to be the one used for the management interface, mainly because at this stage WiFi has not been set up yet. Set up the options as follows&lt;br /&gt;
* Management Interface nic0 (the r8169 is the driver that Debian uses for wired nics) It is the one that is up and the Wifi nic is down so it is straight forward to establish which is which.&lt;br /&gt;
* hostname will be kiwi.seaoffate.net it is safe for us to use this domain name because we have registered it. If the reader has no domain name it could be kiwi.local but it would be unwise to use something that is already register on the public Internet, it may appear to work but there will be odd unforeseen problems like getting updates or push notifications or some other odd thing that don&#039;t work because the reply is being sent to a different IP address.&lt;br /&gt;
* IP address will be 192.168.1.112/24&lt;br /&gt;
* Gateway will be 192.168.1.1&lt;br /&gt;
* DNS will be 192.168.1.1&lt;br /&gt;
When this is done click next for the Summary. Make sure it is all correct and the auto reboot after successful installation then click install.&lt;br /&gt;
&lt;br /&gt;
====Post Installation ====&lt;br /&gt;
&lt;br /&gt;
When the host finishes the install it will restart. It may show the Proxmox Intallation again if the USB is still plugged in depending on the boot options, if so remove the USB and restart the computer. once the computer has finished starting it should show a simple login screen with the web address that is the main administration panel. from this point on the screen, mouse and keyboard can and should be removed as they will probably be never be used again. Now Kiwi will be managed from a web browser. The address will be whatever was set in the Management Network Configuration section with the port number 8006. in the case of Kiwi it is http://192.168.1.112:8006 the browser will give a security warning as no SSL cert has been setup for it yet so click advanced or ignore or whatever the browser needs to get to the web address. Then there will be a bank Proxmox screen with a popup in the middle with the title Proxmox VE Login the login details are&lt;br /&gt;
* Username root&lt;br /&gt;
* Password your_password  ( whatever was set in the password and email section of the instalation)&lt;br /&gt;
* Realm is Linux PAM standard authentication&lt;br /&gt;
* Language English - English&lt;br /&gt;
&#039;&#039;&#039;note&#039;&#039;&#039; username and password are case sensitive&lt;br /&gt;
&lt;br /&gt;
=====Samsung 990 Pro series SSDs Firmware=====&lt;br /&gt;
Now we have logged in we need to check that the Samsung SSD has got up to date firmware, &#039;&#039;&#039;Note This is for Samsung 990 Pro SSDs&#039;&#039;&#039; and not all SSDs it is not even all Samsung SSDs just this particular model in the early versions. Select Kiwi from the left pane then towards the top right of the main pane there is a row of buttons reboot, shutdown, shell, bulk actions, and help click on shell. A new window will appear with root@kiwi already logged in. Type the following into the window&lt;br /&gt;
  smartctl -a /dev/nvme0n1&lt;br /&gt;
look through the information for the SSD, under === START OF INFORMATION SECTION === it should have a firmware Version line. Make sure the version is not &amp;quot;1B2QJXD7&amp;quot; it should be safe if it starts with 3 or more. If the  Samsung 990 Pro SSD does have the unsafe version stop now and update the firmware immediately or it is likely that it will stop working after a short time. The version on this host is Firmware Version: 5B2QJXD7&lt;br /&gt;
&lt;br /&gt;
=====Fix the No Subscription nag and do system update=====&lt;br /&gt;
By default, Proxmox tries to use a paid repository that you can&#039;t access. We need to disable that and add the free community one. This assumes that it is Proxmox version 9.x. Proxmox 9 uses .sources files. We must disable the default enterprise links and add the community repository. Run these commands in the Kiwi shell&lt;br /&gt;
 # 1. Disable Enterprise PVE Repo&lt;br /&gt;
 mv /etc/apt/sources.list.d/pve-enterprise.sources /etc/apt/sources.list.d/pve-enterprise.sources.bak&lt;br /&gt;
 # 2. Disable Enterprise Ceph Repo&lt;br /&gt;
 mv /etc/apt/sources.list.d/ceph.sources /etc/apt/sources.list.d/ceph.sources.bak&lt;br /&gt;
 # 3. Create the No-Subscription Source&lt;br /&gt;
 cat &amp;lt;&amp;lt;EOF &amp;gt; /etc/apt/sources.list.d/pve-no-subscription.sources&lt;br /&gt;
 Types: deb&lt;br /&gt;
 URIs: http://download.proxmox.com/debian/pve&lt;br /&gt;
 Suites: trixie&lt;br /&gt;
 Components: pve-no-subscription&lt;br /&gt;
 Architectures: amd64&lt;br /&gt;
 Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg&lt;br /&gt;
 EOF&lt;br /&gt;
The &amp;quot;No-Nag&amp;quot; UI Patch: This command neutralizes the subscription check in the web interface and restarts the proxy service to apply it&lt;br /&gt;
 # 4. Remove &#039;No Valid Subscription&#039; Login Popup&lt;br /&gt;
 sed -Ezi.bak &amp;quot;s/(Ext.Msg.show\(\{\s+title: gettext\(\&#039;No valid sub)/void\(\{ \/\/\1/g&amp;quot; /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js &amp;amp;&amp;amp; systemctl restart pveproxy.service&lt;br /&gt;
When the system reboots open a new console window for the host. So we can do an update. Always use dist-upgrade for Proxmox to ensure kernel and dependency changes are handled correctly.&lt;br /&gt;
 # 5. Refresh and Upgrade&lt;br /&gt;
 apt update &amp;amp;&amp;amp; apt dist-upgrade -y&lt;br /&gt;
Summary of why we did this&lt;br /&gt;
* The .bak method: Instead of fighting sed patterns that might change, moving the files to .bak is a &amp;quot;bulletproof&amp;quot; way to ensure apt ignores them.&lt;br /&gt;
* Trixie Suites: Using Suites: trixie ensures you aren&#039;t pulling in old bookworm (Proxmox 8) packages that could destabilize your new Ryzen 5 build.&lt;br /&gt;
* The 63 Packages: Now that you&#039;ve run the update, those 63 packages are waiting. Running the dist-upgrade command above will install the latest 2026 security patches and hardware drivers.&lt;br /&gt;
&lt;br /&gt;
=====Ironwolf Pro Harddrive Setup=====&lt;br /&gt;
&lt;br /&gt;
Since we have already performed the dist-upgrade, the kernel is fresh and ready to handle the heavy I/O of those 14TB drives. We will set this up via the CLI to ensure we get the exact optimizations needed for a high-density vault. First, we must be 100% certain which device names (/dev/sdX) belong to the IronWolfs.&lt;br /&gt;
 lsblk -o NAME,SIZE,MODEL,SERIAL&lt;br /&gt;
Look for the three drives that show approximately 12.7T (the TiB equivalent of 14TB). Verify the Model says ST14000.... In this case they are&lt;br /&gt;
* sda  12.7T ST14000NE0008-2JK101    ZTM0D5FK&lt;br /&gt;
* sdb  12.7T ST14000NE0008-2H4101    ZL2EJCXX (this one has a partition sdb1 but we ignore it)&lt;br /&gt;
* sdc  12.7T ST14000NE0008-2JK101    ZTM0D5A0&lt;br /&gt;
The Clean Slate (Wipe the Labels) Run these commands to clear the old ZFS and EFI labels. This doesn&#039;t delete all of the old data (which takes hours), it just &amp;quot;un-formats&amp;quot; the start and end of the disks so ZFS sees them as new. It may not be necessary for all of the drives but certainly is for sdb as that has a partition on it&lt;br /&gt;
 # Wipe the ZFS labels specifically&lt;br /&gt;
 zpool labelclear -f /dev/sda&lt;br /&gt;
 zpool labelclear -f /dev/sdb&lt;br /&gt;
 zpool labelclear -f /dev/sdc&lt;br /&gt;
 # Wipe the partition tables entirely (the &amp;quot;Nuclear&amp;quot; option)&lt;br /&gt;
 wipefs -a /dev/sda&lt;br /&gt;
 wipefs -a /dev/sdb&lt;br /&gt;
 wipefs -a /dev/sdc&lt;br /&gt;
&lt;br /&gt;
The other drive is the 990 Pro SSD. Now we can create the ZFS Z1 Pool We will name the pool kiwipool. We are using ashift=12 for 4K sector alignment and atime=off to save the mechanical heads from unnecessary movement.&lt;br /&gt;
 zpool create -o ashift=12 kiwipool raidz1 /dev/sda /dev/sdb /dev/sdc&lt;br /&gt;
 # Apply optimizations&lt;br /&gt;
 zfs set compression=lz4 kiwipool &lt;br /&gt;
 zfs set atime=off kiwipool &lt;br /&gt;
 zfs set xattr=sa kiwipool &lt;br /&gt;
 zfs set recordsize=1M kiwipool &lt;br /&gt;
once that is done we can verify the pool is built with&lt;br /&gt;
 zpool status kiwipool&lt;br /&gt;
Next we need to make some datasets to keep the pool organised and not write anything to the root of kiwipool. Run thes commands&lt;br /&gt;
 zfs create kiwipool/PFK&lt;br /&gt;
 zfs create kiwipool/PFK/pdata&lt;br /&gt;
 zfs create kiwipool/PFK/pdata/KiwiHDs&lt;br /&gt;
 zfs create kiwipool/ISO&lt;br /&gt;
 zfs create kiwipool/PFK/backups&lt;br /&gt;
 zfs list &lt;br /&gt;
The zpool will show up in the webgui in Kiwi-&amp;gt;storage and kiwi-&amp;gt;zfs but not in the VM list on the left hand pane so they cannot be added to VMs yet. To make them available we run the command&lt;br /&gt;
 pvesm add zfspool KiwiHDs --pool kiwipool/PFK/pdata/KiwiHDs --content rootdir,images&lt;br /&gt;
 pvesm add dir KiwiISOs --path /kiwipool/ISO --content iso,vztmpl&lt;br /&gt;
 pvesm add dir KiwiBackups --path /kiwipool/PFK/backups --content backup&lt;br /&gt;
Now in the webgui there should be the drives for VM HDs, ISOs and backups&lt;br /&gt;
&lt;br /&gt;
=====Check and configure the WiFi=====&lt;br /&gt;
&lt;br /&gt;
Testing Wi-Fi on a Proxmox (Debian) host is a bit different than on a laptop because there is no &amp;quot;taskbar&amp;quot; to click. We have to do this through the CLI. First, let&#039;s see if Debian even sees the Wi-Fi card and has the drivers loaded.&lt;br /&gt;
 ip link&lt;br /&gt;
Look for: An interface starting with w (e.g., wlp2s0 or wlan0). If you don&#039;t see one the drivers might be missing or it&#039;s &amp;quot;Hard Blocked&amp;quot; in the BIOS. In this case The hardware check is a success. Your Wi-Fi card is identified as wlp5s0 (it did show up in the installer but it was ignored then ). The state is currently DOWN, which is expected since it hasn&#039;t been configured with your SSID or credentials yet. Because Proxmox is built for servers, it lacks a graphical Wi-Fi picker. We have to manually tell the background service (wpa_supplicant) how to talk to your router. at the same time install the wireless tools package.&lt;br /&gt;
 apt update &amp;amp;&amp;amp; apt install wpasupplicant wireless-tools -y&lt;br /&gt;
Instead of typing the Wi-Fi password in plain text, we’ll use a tool to generate a secure configuration block. Replace Your_SSID and Your_Password with your actual wireless AP details:&lt;br /&gt;
 wpa_passphrase &amp;quot;Your_SSID&amp;quot; &amp;quot;Your_Password&amp;quot; &amp;gt; /etc/wpa_supplicant/wpa_supplicant.conf&lt;br /&gt;
Now we can test the connection let&#039;s see if Kiwi can actually authenticate.&lt;br /&gt;
 wpa_supplicant -B -i wlp5s0 -c /etc/wpa_supplicant/wpa_supplicant.conf&lt;br /&gt;
Then wait a few seconds before checking the status with &lt;br /&gt;
 iw wlp5s0 link&lt;br /&gt;
Assuming it shows a connection we can make it permanent. To ensure the Wi-Fi comes up automatically on boot and acts as a secondary management port, we need to add it to the network interfaces file. Warning: Be very careful with the syntax here. Use this command to append the configuration to /etc/network/interfaces. cat &amp;lt;&amp;lt;EOF &amp;gt;&amp;gt; /etc/network/interfaces&lt;br /&gt;
 auto wlp5s0&lt;br /&gt;
 iface wlp5s0 inet static&lt;br /&gt;
         address 192.168.1.113/24&lt;br /&gt;
         wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
=====🌐 Networking &amp;amp; The &amp;quot;Wi-Fi Failover&amp;quot; Battle=====&lt;br /&gt;
&lt;br /&gt;
This section documents the attempt to create a reliable wireless &amp;quot;emergency backdoor.&amp;quot; The objective was to have the Wi-Fi (192.168.1.113) act as a secondary management port that remains accessible even if the 2.5G cable is pulled. The Problem was cuased by (Asymmetric Routing). Linux prefers the route with the lowest metric. Since the 2.5G wire has a metric of 10 and Wi-Fi has 100, pulling the cable caused a &amp;quot;Routing Black Hole&amp;quot;—Kiwi would receive requests via Wi-Fi but try to reply via the dead Ethernet cable.&lt;br /&gt;
&lt;br /&gt;
Several fixes were applied including&lt;br /&gt;
* Kernel Routing Tweaks: Added to /etc/sysctl.conf to force the OS to ignore dead routes immediately&lt;br /&gt;
 nano /etc/sysctl.conf&lt;br /&gt;
&lt;br /&gt;
 net.ipv4.conf.all.ignore_routes_with_linkdown=1&lt;br /&gt;
 net.ipv4.conf.default.ignore_routes_with_linkdown=1&lt;br /&gt;
 net.ipv4.conf.all.arp_ignore=1&lt;br /&gt;
 net.ipv4.conf.all.arp_announce=2&lt;br /&gt;
* We tried to create service persistence. We created a systemd override for wpa_supplicant@wlp5s0 to handle driver timing issues&lt;br /&gt;
 [Service]&lt;br /&gt;
 Restart=on-failure&lt;br /&gt;
 RestartSec=5s&lt;br /&gt;
 ExecStartPost=/usr/sbin/ifup wlp5s0 --force&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Proxmox_Server&amp;diff=1511</id>
		<title>Proxmox Server</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Proxmox_Server&amp;diff=1511"/>
		<updated>2026-05-01T07:33:04Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Pear */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==📋Introduction==&lt;br /&gt;
&lt;br /&gt;
This is the server that will sit under my desk until I move house. It has the hostname Pear and will be the beginning of the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;. There is also now a new smaller and less powerful server with the hostname Kiwi.&lt;br /&gt;
&lt;br /&gt;
==🥝[[Create Virtual Machine from a template]]==&lt;br /&gt;
&lt;br /&gt;
it is possible to create a new VM based on a fixed template. The two possibilities are a full clone or a linked clone. the linked clone is the preferred as it should need less storage but the full clone would be completely independent of the template so it will use more storage and take longer to create.We can go down that rabbit hole when we look ant Ansible in a big way. For now just understand that we can call a new vm  using the  qm clone command. the will be more details to follow.&lt;br /&gt;
&lt;br /&gt;
==Orchard (Pear)==&lt;br /&gt;
The first host has Proxmox installed with the following specification&lt;br /&gt;
&lt;br /&gt;
===🛠️Hardware Specification===&lt;br /&gt;
&lt;br /&gt;
The Main components were purchased in 2024 as follows&lt;br /&gt;
&lt;br /&gt;
* The Cpu is AMD Ryzen 9 5950X Processor (16Cores/32Threads, 105W TDP, Socket AM4, 72MB Cache, Up to 4.9 GHz Max Boost, no cooler) £369.98&lt;br /&gt;
* The cooler is Noctua NH-D15, Premium CPU Cooler with 2x NF-A15 PWM 140mm Fans (Brown) £99.95&lt;br /&gt;
* Mainboard is Gigabyte B550M AORUS ELITE Motherboard - Supports AMD Ryzen 5000 Series AM4 CPUs, 5+3 Phases Pure Digital VRM, up to 4733MHz DDR4 (OC), 2xPCIe 3.0 M.2, GbE LAN, USB 3.2 Gen1 £103.48&lt;br /&gt;
* 128gb Ram is configured as two sets of CORSAIR VENGEANCE LPX DDR4 RAM 64GB (2x32GB) 3200MHz CL16-20-20-38 1.35V (CMK64GX4M2E3200C16) £112.20 for one set&lt;br /&gt;
* GPU is a Gigabyte Geforce RTX 5060 TI with 16 GB Ram&lt;br /&gt;
* Power supply is Corsair RM750x 80 Plus Gold Fully Modular ATX 750 Watt Power Supply £109.00&lt;br /&gt;
* The case is Fractal Design Node 804 - Black - Compact Computer Case - mATX - High Airflow - Modular interior - 3x Fractal Design Silent R2 120mm Fans Included - Water-cooling ready - USB 3.0 -Window Side Panel £99.95 &lt;br /&gt;
* SSD is Crucial P3 Plus SSD 4TB M.2 NVMe PCIe Gen4 Internal SSD, Up to 4800MB/s, Laptop &amp;amp; Desktop (PC) Compatible, Solid State Drive - CT4000P3PSSD801 £189.99 and £159.99&lt;br /&gt;
* Three 16 TB Seagate Ironwolf NAS drives make up the hard disk storage at a cost of £179.94 each total £ 539.82.&lt;br /&gt;
* One cheap 1 TB SATA SSD currently set as a L2ARC but may reconfigure as a sacrificial drive for the high wear VMs if it looks like it is not getting many hits as L2ARC &#039;&#039;&#039;Update &#039;&#039;&#039; no longer used as L2ARC and formmated to a zpool fastpool.&lt;br /&gt;
&lt;br /&gt;
===Configuration===&lt;br /&gt;
&lt;br /&gt;
====🌐Network Access====&lt;br /&gt;
&lt;br /&gt;
The IP Address and port of the host is 192.168.0.110:8006. I have my virgin media router forwarding all incoming traffic to 192.168.0.125 so it will go directly to the Pfsense firewall. All of the terminals can also send traffic to the WAN port of Pfsense. &#039;&#039;&#039;Edit&#039;&#039;&#039; with the change to Vodaphone the network address changed to 192.168.1.0/24 so Proxmox console is now 192.168.1.111:8006 and the WAN port of Pfsense is 192.168.1.125. a further change was to only forward those ports that are actually needed to Pfsense because the new ISP router has better options than the really old Virgin media one ( to be fair if i had stayed with Virgin i would have got a newer router). More &#039;&#039;&#039;[[Network Configuration]]&#039;&#039;&#039; details.&lt;br /&gt;
&lt;br /&gt;
====💾Storage====&lt;br /&gt;
&lt;br /&gt;
The main storage is the three 16TB hard drives configure into ZFS z1 so that they have one redundant disk. As one disk is redundant, obviously, it has 32TB of storage available.&lt;br /&gt;
&lt;br /&gt;
I couldn&#039;t get PCI passthrough to work reliably without significant effort and some expense so I set up ZFS on Proxmox itself or more precisely on the Debian Linux that Proxmox resides on. Unfortunately, that means that I have to do any config on the CLI. I may write some scripts to perform some of the admin tasks or more likely setup a Nginx container to automate as much of it as possible. For the time being some useful ZFS commands can be found &#039;&#039;&#039;[[ZFS Commands |here]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==🥝 Kiwi Host: Technical Manual &amp;amp; Build Log==&lt;br /&gt;
&lt;br /&gt;
Kiwi is the secondary Proxmox host in the Home Lab, housed in a Fractal Design ITX chassis. While less powerful than the primary host (Pear), it serves as a high-capacity storage node and 2.5G data target.&lt;br /&gt;
&lt;br /&gt;
=== Hardware Specification ===&lt;br /&gt;
&lt;br /&gt;
* CPU: AMD Ryzen 5 with Stock Wraith Cooler.&lt;br /&gt;
* RAM: 64GB (2x32GB Crucial DDR4), maxing out the two available slots.&lt;br /&gt;
* System Drive: 2TB Samsung 990 Pro NVMe (Firmware verified: 5B2QJXD7).&lt;br /&gt;
* Storage Pool: 3x 14TB Seagate IronWolf Pro HDDs (ZFS RAIDZ1, 28TB usable).&lt;br /&gt;
* Network: Onboard 2.5 Gbps Wired NIC (nic0) + Built-in Wi-Fi (wlp5s0).&lt;br /&gt;
* GPU: Legacy Nvidia GPU (Required for POST and initial installation). The Mainboard has 4 SATA ports on board. Three of them have 14 TB Ironwolf pro drives to be formatted as a ZFS array with Z! so will give 28TB of usable storage with one disk of redundancy&lt;br /&gt;
&lt;br /&gt;
===Proxmox Installation===&lt;br /&gt;
&lt;br /&gt;
It is assumed that the Proxmox installer has been downloaded from their website and the iso has been copied on to a USB stick and made bootable with Rufus or some other similar. If the reader doesn&#039;t know how to make a USB installer from an ISO try typing &amp;quot;How do I make a USB stick into a proxmox installer&amp;quot; in to a browser. there will be loads of guides on how to use Rufus. When a bootable USB stick with Proxmox installer on it has been created insert in to one of the USB slots along with a keyboard, mouse and screen. Please note the keyboard mouse and screen will only be needed for the installation, once Proxmox is installed it is unlikely that these will ever be used again because virtually all administration is performed on a web GUI. &lt;br /&gt;
&lt;br /&gt;
====BIOS settings for Hypervisors (including Proxmox)====&lt;br /&gt;
&lt;br /&gt;
Generally most BIOS can be left at defaults and a PC as a PC will work well enough, maybe the boot priority may need to be changed from a HDD to a SSD but even that is unlikely. It is possible to optimise lots of things in BIOS and for some people that is an option but it is also easy to make mistakes that either stop the machine from working or making the machine unstable so for most people, most of the time, it is better to leave BIOS alone. A big exception is when a hypervisor is to be install because a few options that are off by default need to be set for Virtualisation to work properly. The main things to set are:-&lt;br /&gt;
* SVM Mode (AMD-V): &#039;&#039;&#039;Must be Enabled.&#039;&#039;&#039; This is what allows Proxmox to run VMs. Without it virtualisation will fail with most or possibly all hypervisors&lt;br /&gt;
* IOMMU: Set to Enabled. This is vital if you ever want to &amp;quot;pass through&amp;quot; a SATA controller or GPU directly to a VM. while not vital for the virtualisation itself most hypervisors have this enabled.&lt;br /&gt;
* Power Supply Idle Control: If you find the server randomly freezes when idle, set this to &amp;quot;Typical Current Idle&amp;quot;. Ryzen chips sometimes drop voltage too low for some power supplies when idling, causing a crash. Again not vital but a &amp;quot;nice to have&amp;quot; if possible in the BIOS.&lt;br /&gt;
* Boot options: The SSD should be at the top. It is better to set the USB at the bottom so that if a USB is left in the machine and it is rebooted it doesn&#039;t try to boot from the USB.&lt;br /&gt;
Once the BIOS option are set save the settings and quit. The computer will shutdown and restart, while it is restarting keep pressing the delete key or the F12 key to bring up the boot options (it is usually delete key but it should also display the options briefly on the screen as it starts). &lt;br /&gt;
&lt;br /&gt;
====GPU Considerations====&lt;br /&gt;
&lt;br /&gt;
The Proxmox installation is a little bit more tricky than is standard for the majority of computers in that this has an old GPU that the installer does not recognise. A GPU is required so that the machine will pass POST but is not really need or used by the Proxmox guests so is generally of little benefit for the overall Proxmox day to day running. A lot of Hypervisor hosts have the cheapest and lowest power GPUs installed just enough to POST but no more than that. The reason that GPU is of low priorty for most hypervisors hosts is that they are generally run headless, that is without a monitor attached, all interations with the host is through a dedicated application like Citrix XEN, or more likely through a web browser like Proxmox. Web based GUIs are popular because it is a lot easier and lighter processor load to have a webserver attached than it is to design a whole application. Kiwi has an old Nvidia GPU that works in that it provides a display but that is about it. Unfortunately, it does give some problems for the installer as it is so old but therea re steps to overcome that as will be detailed below. We may add a bigger and better GPU at a later date but for the foreseeable future that is in the realms of an upgrade for later and dependant on inheriting a GPU from another box.&lt;br /&gt;
&lt;br /&gt;
====Proxmox Installer problems (The Kiwi exceptions)====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As stated earlier the Proxmox installer does not work with the GPU. This is shown in that the machine boots and loads the first screen of the installer with welcome to.. but when the first option is tried it starts to load then freezes at the loading Nvidia drivers or some such thing(cant remember exactly what it says). so to fix that issue we need to restart the host and when we get to the welcome screen again we highlight &amp;quot;Install Proxmox VE (Graphical)&amp;quot; but &#039;&#039;&#039;do not press Enter&#039;&#039;&#039; instead we press &amp;quot;e&amp;quot; so a black screen with GNU GRUB appears. Edit the line&lt;br /&gt;
 linux /boot/linux26 ro ramdisk_size=16777216 rw quiet splash=silent&lt;br /&gt;
so it reads &lt;br /&gt;
 linux /boot/linux26 ro ramdisk_size=16777216 rw nomodeset&lt;br /&gt;
* By removing the quiet splash=silent we force the installer to show every single line of code as it loads. If it freezes again, we see the exact driver name where it stopped (e.g., sata_nv or i915).&lt;br /&gt;
* Adding nomodeset: This is the &amp;quot;magic bullet&amp;quot; for the nvidiafb hang. It tells the kernel not to touch the video drivers until the system is fully loaded. It is most likely where the installer hangs. As we should see every line of the execution of the installer if we have a different driver issue we should still see it.&lt;br /&gt;
To save the changes press ctrl+x or maybe F10. The GNU Grub screen will close and the graphical installer will continue until it gets to the &amp;quot;end user license agreement (EULA) screen. For anyone else reading this, If  the installer freezes again before it gets to the EULA screen the error will most likely be in the last laine of text displayed. The most likely error will be a conflict between Debian kernel and Advanced Configuration and Power Interface (ACPI) in which case restart and press the &amp;quot;e&amp;quot; to get to the Grub config and edit the same line &lt;br /&gt;
 linux /boot/linux26 ro ramdisk_size=16777216 rw nomodeset&lt;br /&gt;
so that it now has noapic added. note that this is just for the installer not the Proxmox application. &lt;br /&gt;
 linux /boot/linux26 ro ramdisk_size=16777216 rw nomodeset noapic&lt;br /&gt;
After modifying that line press ctrl+x or F10 to save and proceed. if it stalls again you will need to look for the exact error in the last line or last few lines that the installer performed or any line that starts or ends with failed.&lt;br /&gt;
&lt;br /&gt;
====Proxmox installer continued====&lt;br /&gt;
&lt;br /&gt;
After the earlier problems we should have got to the ELUA screen so press &amp;quot;I agree&amp;quot; button to continue. The next screen will be about choosing hard drives. Kiwi has a single SSD and three Ironwolf Pro 14 TB HDDs. Obviously, we will not install the OS onto a HDD or even all three HDDs as it would be too slow and as the SSD is fast we will choose that as the Target Harddisk. with the SSD selected click on options button.&lt;br /&gt;
* select zfs (RAID0) &lt;br /&gt;
* select samsung SSD as hardisk 0&lt;br /&gt;
* select Do not use for harddisk 1&lt;br /&gt;
* select Do not use for harddisk 2&lt;br /&gt;
* select Do not use for harddisk 3&lt;br /&gt;
ZFS is the best choice as it has native compression, Bitrot detection but not really protection because there is only one drive so nowhere to restore any corrupt data from. ZFS also has good snapshot capability. Ext4 / XFS are &amp;quot;set it and forget it&amp;quot; options. They use almost zero RAM, but they offer no protection against data corruption and have very basic snapshotting capabilities (via LVM).  Btrfs is similar to ZFS but generally considered less stable and has a lower feature set. The HDDs will not be used during the installation of Proxmox because it is easier to set them up from within the Proxmox web GUI or CLI.so the do not use is the best option for now &#039;&#039;&#039;note&#039;&#039;&#039; before we exit the Harddisk Options we need to check that the &#039;&#039;&#039;ashift&#039;&#039;&#039; is set to 12 so that the data blocks align with the physical page size of the Samsung 990 Pro&#039;s NAND, ensuring maximum speed, so select Advanced Options button next to Disk setup. Choose&lt;br /&gt;
* ashift is 12&lt;br /&gt;
* compress is on&lt;br /&gt;
* checksum is on&lt;br /&gt;
* copies is 1. Since this is a single-disk ZFS RAID0, copies=1 is the standard. If it is set it to 2, it would store every block twice on the same physical SSD. While that would allow ZFS to repair bitrot, it would effectively cut the 2TB SSD down to 1TB and halve the write speeds. With a 990 Pro, standard checksums and a good backup strategy are much more efficient.&lt;br /&gt;
* ARC max size 6422 Since there are only have two RAM slots and we are capped at 64GB, we need to be very intentional about how we carve up Kiwi RAM. having said that it is only a Maximum not a set size and zfs does not have to use all of it&#039;s maximum&lt;br /&gt;
* hdsize is set to maximum ( the + button will only allow it to be the size of the harddisk so click it until it stops going up)&lt;br /&gt;
Check the settings and when all looks correct click next for the regional settings&lt;br /&gt;
* Country United Kingdom&lt;br /&gt;
* Timezone Europe/London (or UTC if preferred)&lt;br /&gt;
* Keyboard Layout United Kingdom&lt;br /&gt;
Then next to set password and email address screen. Set a strong password that you can remember for the administration of the host. If the password is lost it will be almost impossible to recover it so do not forget it. Also it will be the hackers dream to get hold of the Proxmox host&#039;s password in that all of the rest of the security is mainly built on top of the administration of the host. If a host in a cluster is compromised it is quite likely that the whole cluster is compromised. The email address is so Proxmox can send promotional or updates but in general they don&#039;t flood their users with spam so it is no problem adding in a real email address. When done Click next to se the Management Network configuration screen.&lt;br /&gt;
&lt;br /&gt;
The Management Network Configuration will determine where the WebGUI will be presented from. Kiwi has two NICs, one is the 2.5 GB p/s wired NIC and the other is the wireless NIC. by default it is likely to be the wired NIC that is going to be the one used for the management interface, mainly because at this stage WiFi has not been set up yet. Set up the options as follows&lt;br /&gt;
* Management Interface nic0 (the r8169 is the driver that Debian uses for wired nics) It is the one that is up and the Wifi nic is down so it is straight forward to establish which is which.&lt;br /&gt;
* hostname will be kiwi.seaoffate.net it is safe for us to use this domain name because we have registered it. If the reader has no domain name it could be kiwi.local but it would be unwise to use something that is already register on the public Internet, it may appear to work but there will be odd unforeseen problems like getting updates or push notifications or some other odd thing that don&#039;t work because the reply is being sent to a different IP address.&lt;br /&gt;
* IP address will be 192.168.1.112/24&lt;br /&gt;
* Gateway will be 192.168.1.1&lt;br /&gt;
* DNS will be 192.168.1.1&lt;br /&gt;
When this is done click next for the Summary. Make sure it is all correct and the auto reboot after successful installation then click install.&lt;br /&gt;
&lt;br /&gt;
====Post Installation ====&lt;br /&gt;
&lt;br /&gt;
When the host finishes the install it will restart. It may show the Proxmox Intallation again if the USB is still plugged in depending on the boot options, if so remove the USB and restart the computer. once the computer has finished starting it should show a simple login screen with the web address that is the main administration panel. from this point on the screen, mouse and keyboard can and should be removed as they will probably be never be used again. Now Kiwi will be managed from a web browser. The address will be whatever was set in the Management Network Configuration section with the port number 8006. in the case of Kiwi it is http://192.168.1.112:8006 the browser will give a security warning as no SSL cert has been setup for it yet so click advanced or ignore or whatever the browser needs to get to the web address. Then there will be a bank Proxmox screen with a popup in the middle with the title Proxmox VE Login the login details are&lt;br /&gt;
* Username root&lt;br /&gt;
* Password your_password  ( whatever was set in the password and email section of the instalation)&lt;br /&gt;
* Realm is Linux PAM standard authentication&lt;br /&gt;
* Language English - English&lt;br /&gt;
&#039;&#039;&#039;note&#039;&#039;&#039; username and password are case sensitive&lt;br /&gt;
&lt;br /&gt;
=====Samsung 990 Pro series SSDs Firmware=====&lt;br /&gt;
Now we have logged in we need to check that the Samsung SSD has got up to date firmware, &#039;&#039;&#039;Note This is for Samsung 990 Pro SSDs&#039;&#039;&#039; and not all SSDs it is not even all Samsung SSDs just this particular model in the early versions. Select Kiwi from the left pane then towards the top right of the main pane there is a row of buttons reboot, shutdown, shell, bulk actions, and help click on shell. A new window will appear with root@kiwi already logged in. Type the following into the window&lt;br /&gt;
  smartctl -a /dev/nvme0n1&lt;br /&gt;
look through the information for the SSD, under === START OF INFORMATION SECTION === it should have a firmware Version line. Make sure the version is not &amp;quot;1B2QJXD7&amp;quot; it should be safe if it starts with 3 or more. If the  Samsung 990 Pro SSD does have the unsafe version stop now and update the firmware immediately or it is likely that it will stop working after a short time. The version on this host is Firmware Version: 5B2QJXD7&lt;br /&gt;
&lt;br /&gt;
=====Fix the No Subscription nag and do system update=====&lt;br /&gt;
By default, Proxmox tries to use a paid repository that you can&#039;t access. We need to disable that and add the free community one. This assumes that it is Proxmox version 9.x. Proxmox 9 uses .sources files. We must disable the default enterprise links and add the community repository. Run these commands in the Kiwi shell&lt;br /&gt;
 # 1. Disable Enterprise PVE Repo&lt;br /&gt;
 mv /etc/apt/sources.list.d/pve-enterprise.sources /etc/apt/sources.list.d/pve-enterprise.sources.bak&lt;br /&gt;
 # 2. Disable Enterprise Ceph Repo&lt;br /&gt;
 mv /etc/apt/sources.list.d/ceph.sources /etc/apt/sources.list.d/ceph.sources.bak&lt;br /&gt;
 # 3. Create the No-Subscription Source&lt;br /&gt;
 cat &amp;lt;&amp;lt;EOF &amp;gt; /etc/apt/sources.list.d/pve-no-subscription.sources&lt;br /&gt;
 Types: deb&lt;br /&gt;
 URIs: http://download.proxmox.com/debian/pve&lt;br /&gt;
 Suites: trixie&lt;br /&gt;
 Components: pve-no-subscription&lt;br /&gt;
 Architectures: amd64&lt;br /&gt;
 Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg&lt;br /&gt;
 EOF&lt;br /&gt;
The &amp;quot;No-Nag&amp;quot; UI Patch: This command neutralizes the subscription check in the web interface and restarts the proxy service to apply it&lt;br /&gt;
 # 4. Remove &#039;No Valid Subscription&#039; Login Popup&lt;br /&gt;
 sed -Ezi.bak &amp;quot;s/(Ext.Msg.show\(\{\s+title: gettext\(\&#039;No valid sub)/void\(\{ \/\/\1/g&amp;quot; /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js &amp;amp;&amp;amp; systemctl restart pveproxy.service&lt;br /&gt;
When the system reboots open a new console window for the host. So we can do an update. Always use dist-upgrade for Proxmox to ensure kernel and dependency changes are handled correctly.&lt;br /&gt;
 # 5. Refresh and Upgrade&lt;br /&gt;
 apt update &amp;amp;&amp;amp; apt dist-upgrade -y&lt;br /&gt;
Summary of why we did this&lt;br /&gt;
* The .bak method: Instead of fighting sed patterns that might change, moving the files to .bak is a &amp;quot;bulletproof&amp;quot; way to ensure apt ignores them.&lt;br /&gt;
* Trixie Suites: Using Suites: trixie ensures you aren&#039;t pulling in old bookworm (Proxmox 8) packages that could destabilize your new Ryzen 5 build.&lt;br /&gt;
* The 63 Packages: Now that you&#039;ve run the update, those 63 packages are waiting. Running the dist-upgrade command above will install the latest 2026 security patches and hardware drivers.&lt;br /&gt;
&lt;br /&gt;
=====Ironwolf Pro Harddrive Setup=====&lt;br /&gt;
&lt;br /&gt;
Since we have already performed the dist-upgrade, the kernel is fresh and ready to handle the heavy I/O of those 14TB drives. We will set this up via the CLI to ensure we get the exact optimizations needed for a high-density vault. First, we must be 100% certain which device names (/dev/sdX) belong to the IronWolfs.&lt;br /&gt;
 lsblk -o NAME,SIZE,MODEL,SERIAL&lt;br /&gt;
Look for the three drives that show approximately 12.7T (the TiB equivalent of 14TB). Verify the Model says ST14000.... In this case they are&lt;br /&gt;
* sda  12.7T ST14000NE0008-2JK101    ZTM0D5FK&lt;br /&gt;
* sdb  12.7T ST14000NE0008-2H4101    ZL2EJCXX (this one has a partition sdb1 but we ignore it)&lt;br /&gt;
* sdc  12.7T ST14000NE0008-2JK101    ZTM0D5A0&lt;br /&gt;
The Clean Slate (Wipe the Labels) Run these commands to clear the old ZFS and EFI labels. This doesn&#039;t delete all of the old data (which takes hours), it just &amp;quot;un-formats&amp;quot; the start and end of the disks so ZFS sees them as new. It may not be necessary for all of the drives but certainly is for sdb as that has a partition on it&lt;br /&gt;
 # Wipe the ZFS labels specifically&lt;br /&gt;
 zpool labelclear -f /dev/sda&lt;br /&gt;
 zpool labelclear -f /dev/sdb&lt;br /&gt;
 zpool labelclear -f /dev/sdc&lt;br /&gt;
 # Wipe the partition tables entirely (the &amp;quot;Nuclear&amp;quot; option)&lt;br /&gt;
 wipefs -a /dev/sda&lt;br /&gt;
 wipefs -a /dev/sdb&lt;br /&gt;
 wipefs -a /dev/sdc&lt;br /&gt;
&lt;br /&gt;
The other drive is the 990 Pro SSD. Now we can create the ZFS Z1 Pool We will name the pool kiwipool. We are using ashift=12 for 4K sector alignment and atime=off to save the mechanical heads from unnecessary movement.&lt;br /&gt;
 zpool create -o ashift=12 kiwipool raidz1 /dev/sda /dev/sdb /dev/sdc&lt;br /&gt;
 # Apply optimizations&lt;br /&gt;
 zfs set compression=lz4 kiwipool &lt;br /&gt;
 zfs set atime=off kiwipool &lt;br /&gt;
 zfs set xattr=sa kiwipool &lt;br /&gt;
 zfs set recordsize=1M kiwipool &lt;br /&gt;
once that is done we can verify the pool is built with&lt;br /&gt;
 zpool status kiwipool&lt;br /&gt;
Next we need to make some datasets to keep the pool organised and not write anything to the root of kiwipool. Run thes commands&lt;br /&gt;
 zfs create kiwipool/PFK&lt;br /&gt;
 zfs create kiwipool/PFK/pdata&lt;br /&gt;
 zfs create kiwipool/PFK/pdata/KiwiHDs&lt;br /&gt;
 zfs create kiwipool/ISO&lt;br /&gt;
 zfs create kiwipool/PFK/backups&lt;br /&gt;
 zfs list &lt;br /&gt;
The zpool will show up in the webgui in Kiwi-&amp;gt;storage and kiwi-&amp;gt;zfs but not in the VM list on the left hand pane so they cannot be added to VMs yet. To make them available we run the command&lt;br /&gt;
 pvesm add zfspool KiwiHDs --pool kiwipool/PFK/pdata/KiwiHDs --content rootdir,images&lt;br /&gt;
 pvesm add dir KiwiISOs --path /kiwipool/ISO --content iso,vztmpl&lt;br /&gt;
 pvesm add dir KiwiBackups --path /kiwipool/PFK/backups --content backup&lt;br /&gt;
Now in the webgui there should be the drives for VM HDs, ISOs and backups&lt;br /&gt;
&lt;br /&gt;
=====Check and configure the WiFi=====&lt;br /&gt;
&lt;br /&gt;
Testing Wi-Fi on a Proxmox (Debian) host is a bit different than on a laptop because there is no &amp;quot;taskbar&amp;quot; to click. We have to do this through the CLI. First, let&#039;s see if Debian even sees the Wi-Fi card and has the drivers loaded.&lt;br /&gt;
 ip link&lt;br /&gt;
Look for: An interface starting with w (e.g., wlp2s0 or wlan0). If you don&#039;t see one the drivers might be missing or it&#039;s &amp;quot;Hard Blocked&amp;quot; in the BIOS. In this case The hardware check is a success. Your Wi-Fi card is identified as wlp5s0 (it did show up in the installer but it was ignored then ). The state is currently DOWN, which is expected since it hasn&#039;t been configured with your SSID or credentials yet. Because Proxmox is built for servers, it lacks a graphical Wi-Fi picker. We have to manually tell the background service (wpa_supplicant) how to talk to your router. at the same time install the wireless tools package.&lt;br /&gt;
 apt update &amp;amp;&amp;amp; apt install wpasupplicant wireless-tools -y&lt;br /&gt;
Instead of typing the Wi-Fi password in plain text, we’ll use a tool to generate a secure configuration block. Replace Your_SSID and Your_Password with your actual wireless AP details:&lt;br /&gt;
 wpa_passphrase &amp;quot;Your_SSID&amp;quot; &amp;quot;Your_Password&amp;quot; &amp;gt; /etc/wpa_supplicant/wpa_supplicant.conf&lt;br /&gt;
Now we can test the connection let&#039;s see if Kiwi can actually authenticate.&lt;br /&gt;
 wpa_supplicant -B -i wlp5s0 -c /etc/wpa_supplicant/wpa_supplicant.conf&lt;br /&gt;
Then wait a few seconds before checking the status with &lt;br /&gt;
 iw wlp5s0 link&lt;br /&gt;
Assuming it shows a connection we can make it permanent. To ensure the Wi-Fi comes up automatically on boot and acts as a secondary management port, we need to add it to the network interfaces file. Warning: Be very careful with the syntax here. Use this command to append the configuration to /etc/network/interfaces. cat &amp;lt;&amp;lt;EOF &amp;gt;&amp;gt; /etc/network/interfaces&lt;br /&gt;
 auto wlp5s0&lt;br /&gt;
 iface wlp5s0 inet static&lt;br /&gt;
         address 192.168.1.113/24&lt;br /&gt;
         wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
=====🌐 Networking &amp;amp; The &amp;quot;Wi-Fi Failover&amp;quot; Battle=====&lt;br /&gt;
&lt;br /&gt;
This section documents the attempt to create a reliable wireless &amp;quot;emergency backdoor.&amp;quot; The objective was to have the Wi-Fi (192.168.1.113) act as a secondary management port that remains accessible even if the 2.5G cable is pulled. The Problem was cuased by (Asymmetric Routing). Linux prefers the route with the lowest metric. Since the 2.5G wire has a metric of 10 and Wi-Fi has 100, pulling the cable caused a &amp;quot;Routing Black Hole&amp;quot;—Kiwi would receive requests via Wi-Fi but try to reply via the dead Ethernet cable.&lt;br /&gt;
&lt;br /&gt;
Several fixes were applied including&lt;br /&gt;
* Kernel Routing Tweaks: Added to /etc/sysctl.conf to force the OS to ignore dead routes immediately&lt;br /&gt;
 nano /etc/sysctl.conf&lt;br /&gt;
&lt;br /&gt;
 net.ipv4.conf.all.ignore_routes_with_linkdown=1&lt;br /&gt;
 net.ipv4.conf.default.ignore_routes_with_linkdown=1&lt;br /&gt;
 net.ipv4.conf.all.arp_ignore=1&lt;br /&gt;
 net.ipv4.conf.all.arp_announce=2&lt;br /&gt;
* We tried to create service persistence. We created a systemd override for wpa_supplicant@wlp5s0 to handle driver timing issues&lt;br /&gt;
 [Service]&lt;br /&gt;
 Restart=on-failure&lt;br /&gt;
 RestartSec=5s&lt;br /&gt;
 ExecStartPost=/usr/sbin/ifup wlp5s0 --force&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Proxmox_Server&amp;diff=1510</id>
		<title>Proxmox Server</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Proxmox_Server&amp;diff=1510"/>
		<updated>2026-05-01T04:35:52Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* 🌐Network Access */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==📋Introduction==&lt;br /&gt;
&lt;br /&gt;
This is the server that will sit under my desk until I move house. It has the hostname Pear and will be the beginning of the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;. There is also now a new smaller and less powerful server with the hostname Kiwi.&lt;br /&gt;
&lt;br /&gt;
==🥝[[Create Virtual Machine from a template]]==&lt;br /&gt;
&lt;br /&gt;
it is possible to create a new VM based on a fixed template. The two possibilities are a full clone or a linked clone. the linked clone is the preferred as it should need less storage but the full clone would be completely independent of the template so it will use more storage and take longer to create.We can go down that rabbit hole when we look ant Ansible in a big way. For now just understand that we can call a new vm  using the  qm clone command. the will be more details to follow.&lt;br /&gt;
&lt;br /&gt;
==Pear==&lt;br /&gt;
The first host has Proxmox installed with the following specificatio&lt;br /&gt;
&lt;br /&gt;
===🛠️Hardware Specification===&lt;br /&gt;
&lt;br /&gt;
The Main components were purchased in 2024 as follows&lt;br /&gt;
&lt;br /&gt;
* The Cpu is AMD Ryzen 9 5950X Processor (16Cores/32Threads, 105W TDP, Socket AM4, 72MB Cache, Up to 4.9 GHz Max Boost, no cooler) £369.98&lt;br /&gt;
* The cooler is Noctua NH-D15, Premium CPU Cooler with 2x NF-A15 PWM 140mm Fans (Brown) £99.95&lt;br /&gt;
* Mainboard is Gigabyte B550M AORUS ELITE Motherboard - Supports AMD Ryzen 5000 Series AM4 CPUs, 5+3 Phases Pure Digital VRM, up to 4733MHz DDR4 (OC), 2xPCIe 3.0 M.2, GbE LAN, USB 3.2 Gen1 £103.48&lt;br /&gt;
* 128gb Ram is configured as two sets of CORSAIR VENGEANCE LPX DDR4 RAM 64GB (2x32GB) 3200MHz CL16-20-20-38 1.35V (CMK64GX4M2E3200C16) £112.20 for one set&lt;br /&gt;
* GPU is a Gigabyte Geforce RTX 5060 TI with 16 GB Ram&lt;br /&gt;
* Power supply is Corsair RM750x 80 Plus Gold Fully Modular ATX 750 Watt Power Supply £109.00&lt;br /&gt;
* The case is Fractal Design Node 804 - Black - Compact Computer Case - mATX - High Airflow - Modular interior - 3x Fractal Design Silent R2 120mm Fans Included - Water-cooling ready - USB 3.0 -Window Side Panel £99.95 &lt;br /&gt;
* SSD is Crucial P3 Plus SSD 4TB M.2 NVMe PCIe Gen4 Internal SSD, Up to 4800MB/s, Laptop &amp;amp; Desktop (PC) Compatible, Solid State Drive - CT4000P3PSSD801 £189.99 and £159.99&lt;br /&gt;
* Three 16 TB Seagate Ironwolf NAS drives make up the hard disk storage at a cost of £179.94 each total £ 539.82.&lt;br /&gt;
* One cheap 1 TB SATA SSD currently set as a L2ARC but may reconfigure as a sacrificial drive for the high wear VMs if it looks like it is not getting many hits as L2ARC &#039;&#039;&#039;Update &#039;&#039;&#039; no longer used as L2ARC and formmated to a zpool fastpool.&lt;br /&gt;
&lt;br /&gt;
===Configuration===&lt;br /&gt;
&lt;br /&gt;
====🌐Network Access====&lt;br /&gt;
&lt;br /&gt;
The IP Address and port of the host is 192.168.0.110:8006. I have my virgin media router forwarding all incoming traffic to 192.168.0.125 so it will go directly to the Pfsense firewall. All of the terminals can also send traffic to the WAN port of Pfsense. &#039;&#039;&#039;Edit&#039;&#039;&#039; with the change to Vodaphone the network address changed to 192.168.1.0/24 so Proxmox console is now 192.168.1.111:8006 and the WAN port of Pfsense is 192.168.1.125. a further change was to only forward those ports that are actually needed to Pfsense because the new ISP router has better options than the really old Virgin media one ( to be fair if i had stayed with Virgin i would have got a newer router). More &#039;&#039;&#039;[[Network Configuration]]&#039;&#039;&#039; details.&lt;br /&gt;
&lt;br /&gt;
====💾Storage====&lt;br /&gt;
&lt;br /&gt;
The main storage is the three 16TB hard drives configure into ZFS z1 so that they have one redundant disk. As one disk is redundant, obviously, it has 32TB of storage available.&lt;br /&gt;
&lt;br /&gt;
I couldn&#039;t get PCI passthrough to work reliably without significant effort and some expense so I set up ZFS on Proxmox itself or more precisely on the Debian Linux that Proxmox resides on. Unfortunately, that means that I have to do any config on the CLI. I may write some scripts to perform some of the admin tasks or more likely setup a Nginx container to automate as much of it as possible. For the time being some useful ZFS commands can be found &#039;&#039;&#039;[[ZFS Commands |here]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==🥝 Kiwi Host: Technical Manual &amp;amp; Build Log==&lt;br /&gt;
&lt;br /&gt;
Kiwi is the secondary Proxmox host in the Home Lab, housed in a Fractal Design ITX chassis. While less powerful than the primary host (Pear), it serves as a high-capacity storage node and 2.5G data target.&lt;br /&gt;
&lt;br /&gt;
=== Hardware Specification ===&lt;br /&gt;
&lt;br /&gt;
* CPU: AMD Ryzen 5 with Stock Wraith Cooler.&lt;br /&gt;
* RAM: 64GB (2x32GB Crucial DDR4), maxing out the two available slots.&lt;br /&gt;
* System Drive: 2TB Samsung 990 Pro NVMe (Firmware verified: 5B2QJXD7).&lt;br /&gt;
* Storage Pool: 3x 14TB Seagate IronWolf Pro HDDs (ZFS RAIDZ1, 28TB usable).&lt;br /&gt;
* Network: Onboard 2.5 Gbps Wired NIC (nic0) + Built-in Wi-Fi (wlp5s0).&lt;br /&gt;
* GPU: Legacy Nvidia GPU (Required for POST and initial installation). The Mainboard has 4 SATA ports on board. Three of them have 14 TB Ironwolf pro drives to be formatted as a ZFS array with Z! so will give 28TB of usable storage with one disk of redundancy&lt;br /&gt;
&lt;br /&gt;
===Proxmox Installation===&lt;br /&gt;
&lt;br /&gt;
It is assumed that the Proxmox installer has been downloaded from their website and the iso has been copied on to a USB stick and made bootable with Rufus or some other similar. If the reader doesn&#039;t know how to make a USB installer from an ISO try typing &amp;quot;How do I make a USB stick into a proxmox installer&amp;quot; in to a browser. there will be loads of guides on how to use Rufus. When a bootable USB stick with Proxmox installer on it has been created insert in to one of the USB slots along with a keyboard, mouse and screen. Please note the keyboard mouse and screen will only be needed for the installation, once Proxmox is installed it is unlikely that these will ever be used again because virtually all administration is performed on a web GUI. &lt;br /&gt;
&lt;br /&gt;
====BIOS settings for Hypervisors (including Proxmox)====&lt;br /&gt;
&lt;br /&gt;
Generally most BIOS can be left at defaults and a PC as a PC will work well enough, maybe the boot priority may need to be changed from a HDD to a SSD but even that is unlikely. It is possible to optimise lots of things in BIOS and for some people that is an option but it is also easy to make mistakes that either stop the machine from working or making the machine unstable so for most people, most of the time, it is better to leave BIOS alone. A big exception is when a hypervisor is to be install because a few options that are off by default need to be set for Virtualisation to work properly. The main things to set are:-&lt;br /&gt;
* SVM Mode (AMD-V): &#039;&#039;&#039;Must be Enabled.&#039;&#039;&#039; This is what allows Proxmox to run VMs. Without it virtualisation will fail with most or possibly all hypervisors&lt;br /&gt;
* IOMMU: Set to Enabled. This is vital if you ever want to &amp;quot;pass through&amp;quot; a SATA controller or GPU directly to a VM. while not vital for the virtualisation itself most hypervisors have this enabled.&lt;br /&gt;
* Power Supply Idle Control: If you find the server randomly freezes when idle, set this to &amp;quot;Typical Current Idle&amp;quot;. Ryzen chips sometimes drop voltage too low for some power supplies when idling, causing a crash. Again not vital but a &amp;quot;nice to have&amp;quot; if possible in the BIOS.&lt;br /&gt;
* Boot options: The SSD should be at the top. It is better to set the USB at the bottom so that if a USB is left in the machine and it is rebooted it doesn&#039;t try to boot from the USB.&lt;br /&gt;
Once the BIOS option are set save the settings and quit. The computer will shutdown and restart, while it is restarting keep pressing the delete key or the F12 key to bring up the boot options (it is usually delete key but it should also display the options briefly on the screen as it starts). &lt;br /&gt;
&lt;br /&gt;
====GPU Considerations====&lt;br /&gt;
&lt;br /&gt;
The Proxmox installation is a little bit more tricky than is standard for the majority of computers in that this has an old GPU that the installer does not recognise. A GPU is required so that the machine will pass POST but is not really need or used by the Proxmox guests so is generally of little benefit for the overall Proxmox day to day running. A lot of Hypervisor hosts have the cheapest and lowest power GPUs installed just enough to POST but no more than that. The reason that GPU is of low priorty for most hypervisors hosts is that they are generally run headless, that is without a monitor attached, all interations with the host is through a dedicated application like Citrix XEN, or more likely through a web browser like Proxmox. Web based GUIs are popular because it is a lot easier and lighter processor load to have a webserver attached than it is to design a whole application. Kiwi has an old Nvidia GPU that works in that it provides a display but that is about it. Unfortunately, it does give some problems for the installer as it is so old but therea re steps to overcome that as will be detailed below. We may add a bigger and better GPU at a later date but for the foreseeable future that is in the realms of an upgrade for later and dependant on inheriting a GPU from another box.&lt;br /&gt;
&lt;br /&gt;
====Proxmox Installer problems (The Kiwi exceptions)====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As stated earlier the Proxmox installer does not work with the GPU. This is shown in that the machine boots and loads the first screen of the installer with welcome to.. but when the first option is tried it starts to load then freezes at the loading Nvidia drivers or some such thing(cant remember exactly what it says). so to fix that issue we need to restart the host and when we get to the welcome screen again we highlight &amp;quot;Install Proxmox VE (Graphical)&amp;quot; but &#039;&#039;&#039;do not press Enter&#039;&#039;&#039; instead we press &amp;quot;e&amp;quot; so a black screen with GNU GRUB appears. Edit the line&lt;br /&gt;
 linux /boot/linux26 ro ramdisk_size=16777216 rw quiet splash=silent&lt;br /&gt;
so it reads &lt;br /&gt;
 linux /boot/linux26 ro ramdisk_size=16777216 rw nomodeset&lt;br /&gt;
* By removing the quiet splash=silent we force the installer to show every single line of code as it loads. If it freezes again, we see the exact driver name where it stopped (e.g., sata_nv or i915).&lt;br /&gt;
* Adding nomodeset: This is the &amp;quot;magic bullet&amp;quot; for the nvidiafb hang. It tells the kernel not to touch the video drivers until the system is fully loaded. It is most likely where the installer hangs. As we should see every line of the execution of the installer if we have a different driver issue we should still see it.&lt;br /&gt;
To save the changes press ctrl+x or maybe F10. The GNU Grub screen will close and the graphical installer will continue until it gets to the &amp;quot;end user license agreement (EULA) screen. For anyone else reading this, If  the installer freezes again before it gets to the EULA screen the error will most likely be in the last laine of text displayed. The most likely error will be a conflict between Debian kernel and Advanced Configuration and Power Interface (ACPI) in which case restart and press the &amp;quot;e&amp;quot; to get to the Grub config and edit the same line &lt;br /&gt;
 linux /boot/linux26 ro ramdisk_size=16777216 rw nomodeset&lt;br /&gt;
so that it now has noapic added. note that this is just for the installer not the Proxmox application. &lt;br /&gt;
 linux /boot/linux26 ro ramdisk_size=16777216 rw nomodeset noapic&lt;br /&gt;
After modifying that line press ctrl+x or F10 to save and proceed. if it stalls again you will need to look for the exact error in the last line or last few lines that the installer performed or any line that starts or ends with failed.&lt;br /&gt;
&lt;br /&gt;
====Proxmox installer continued====&lt;br /&gt;
&lt;br /&gt;
After the earlier problems we should have got to the ELUA screen so press &amp;quot;I agree&amp;quot; button to continue. The next screen will be about choosing hard drives. Kiwi has a single SSD and three Ironwolf Pro 14 TB HDDs. Obviously, we will not install the OS onto a HDD or even all three HDDs as it would be too slow and as the SSD is fast we will choose that as the Target Harddisk. with the SSD selected click on options button.&lt;br /&gt;
* select zfs (RAID0) &lt;br /&gt;
* select samsung SSD as hardisk 0&lt;br /&gt;
* select Do not use for harddisk 1&lt;br /&gt;
* select Do not use for harddisk 2&lt;br /&gt;
* select Do not use for harddisk 3&lt;br /&gt;
ZFS is the best choice as it has native compression, Bitrot detection but not really protection because there is only one drive so nowhere to restore any corrupt data from. ZFS also has good snapshot capability. Ext4 / XFS are &amp;quot;set it and forget it&amp;quot; options. They use almost zero RAM, but they offer no protection against data corruption and have very basic snapshotting capabilities (via LVM).  Btrfs is similar to ZFS but generally considered less stable and has a lower feature set. The HDDs will not be used during the installation of Proxmox because it is easier to set them up from within the Proxmox web GUI or CLI.so the do not use is the best option for now &#039;&#039;&#039;note&#039;&#039;&#039; before we exit the Harddisk Options we need to check that the &#039;&#039;&#039;ashift&#039;&#039;&#039; is set to 12 so that the data blocks align with the physical page size of the Samsung 990 Pro&#039;s NAND, ensuring maximum speed, so select Advanced Options button next to Disk setup. Choose&lt;br /&gt;
* ashift is 12&lt;br /&gt;
* compress is on&lt;br /&gt;
* checksum is on&lt;br /&gt;
* copies is 1. Since this is a single-disk ZFS RAID0, copies=1 is the standard. If it is set it to 2, it would store every block twice on the same physical SSD. While that would allow ZFS to repair bitrot, it would effectively cut the 2TB SSD down to 1TB and halve the write speeds. With a 990 Pro, standard checksums and a good backup strategy are much more efficient.&lt;br /&gt;
* ARC max size 6422 Since there are only have two RAM slots and we are capped at 64GB, we need to be very intentional about how we carve up Kiwi RAM. having said that it is only a Maximum not a set size and zfs does not have to use all of it&#039;s maximum&lt;br /&gt;
* hdsize is set to maximum ( the + button will only allow it to be the size of the harddisk so click it until it stops going up)&lt;br /&gt;
Check the settings and when all looks correct click next for the regional settings&lt;br /&gt;
* Country United Kingdom&lt;br /&gt;
* Timezone Europe/London (or UTC if preferred)&lt;br /&gt;
* Keyboard Layout United Kingdom&lt;br /&gt;
Then next to set password and email address screen. Set a strong password that you can remember for the administration of the host. If the password is lost it will be almost impossible to recover it so do not forget it. Also it will be the hackers dream to get hold of the Proxmox host&#039;s password in that all of the rest of the security is mainly built on top of the administration of the host. If a host in a cluster is compromised it is quite likely that the whole cluster is compromised. The email address is so Proxmox can send promotional or updates but in general they don&#039;t flood their users with spam so it is no problem adding in a real email address. When done Click next to se the Management Network configuration screen.&lt;br /&gt;
&lt;br /&gt;
The Management Network Configuration will determine where the WebGUI will be presented from. Kiwi has two NICs, one is the 2.5 GB p/s wired NIC and the other is the wireless NIC. by default it is likely to be the wired NIC that is going to be the one used for the management interface, mainly because at this stage WiFi has not been set up yet. Set up the options as follows&lt;br /&gt;
* Management Interface nic0 (the r8169 is the driver that Debian uses for wired nics) It is the one that is up and the Wifi nic is down so it is straight forward to establish which is which.&lt;br /&gt;
* hostname will be kiwi.seaoffate.net it is safe for us to use this domain name because we have registered it. If the reader has no domain name it could be kiwi.local but it would be unwise to use something that is already register on the public Internet, it may appear to work but there will be odd unforeseen problems like getting updates or push notifications or some other odd thing that don&#039;t work because the reply is being sent to a different IP address.&lt;br /&gt;
* IP address will be 192.168.1.112/24&lt;br /&gt;
* Gateway will be 192.168.1.1&lt;br /&gt;
* DNS will be 192.168.1.1&lt;br /&gt;
When this is done click next for the Summary. Make sure it is all correct and the auto reboot after successful installation then click install.&lt;br /&gt;
&lt;br /&gt;
====Post Installation ====&lt;br /&gt;
&lt;br /&gt;
When the host finishes the install it will restart. It may show the Proxmox Intallation again if the USB is still plugged in depending on the boot options, if so remove the USB and restart the computer. once the computer has finished starting it should show a simple login screen with the web address that is the main administration panel. from this point on the screen, mouse and keyboard can and should be removed as they will probably be never be used again. Now Kiwi will be managed from a web browser. The address will be whatever was set in the Management Network Configuration section with the port number 8006. in the case of Kiwi it is http://192.168.1.112:8006 the browser will give a security warning as no SSL cert has been setup for it yet so click advanced or ignore or whatever the browser needs to get to the web address. Then there will be a bank Proxmox screen with a popup in the middle with the title Proxmox VE Login the login details are&lt;br /&gt;
* Username root&lt;br /&gt;
* Password your_password  ( whatever was set in the password and email section of the instalation)&lt;br /&gt;
* Realm is Linux PAM standard authentication&lt;br /&gt;
* Language English - English&lt;br /&gt;
&#039;&#039;&#039;note&#039;&#039;&#039; username and password are case sensitive&lt;br /&gt;
&lt;br /&gt;
=====Samsung 990 Pro series SSDs Firmware=====&lt;br /&gt;
Now we have logged in we need to check that the Samsung SSD has got up to date firmware, &#039;&#039;&#039;Note This is for Samsung 990 Pro SSDs&#039;&#039;&#039; and not all SSDs it is not even all Samsung SSDs just this particular model in the early versions. Select Kiwi from the left pane then towards the top right of the main pane there is a row of buttons reboot, shutdown, shell, bulk actions, and help click on shell. A new window will appear with root@kiwi already logged in. Type the following into the window&lt;br /&gt;
  smartctl -a /dev/nvme0n1&lt;br /&gt;
look through the information for the SSD, under === START OF INFORMATION SECTION === it should have a firmware Version line. Make sure the version is not &amp;quot;1B2QJXD7&amp;quot; it should be safe if it starts with 3 or more. If the  Samsung 990 Pro SSD does have the unsafe version stop now and update the firmware immediately or it is likely that it will stop working after a short time. The version on this host is Firmware Version: 5B2QJXD7&lt;br /&gt;
&lt;br /&gt;
=====Fix the No Subscription nag and do system update=====&lt;br /&gt;
By default, Proxmox tries to use a paid repository that you can&#039;t access. We need to disable that and add the free community one. This assumes that it is Proxmox version 9.x. Proxmox 9 uses .sources files. We must disable the default enterprise links and add the community repository. Run these commands in the Kiwi shell&lt;br /&gt;
 # 1. Disable Enterprise PVE Repo&lt;br /&gt;
 mv /etc/apt/sources.list.d/pve-enterprise.sources /etc/apt/sources.list.d/pve-enterprise.sources.bak&lt;br /&gt;
 # 2. Disable Enterprise Ceph Repo&lt;br /&gt;
 mv /etc/apt/sources.list.d/ceph.sources /etc/apt/sources.list.d/ceph.sources.bak&lt;br /&gt;
 # 3. Create the No-Subscription Source&lt;br /&gt;
 cat &amp;lt;&amp;lt;EOF &amp;gt; /etc/apt/sources.list.d/pve-no-subscription.sources&lt;br /&gt;
 Types: deb&lt;br /&gt;
 URIs: http://download.proxmox.com/debian/pve&lt;br /&gt;
 Suites: trixie&lt;br /&gt;
 Components: pve-no-subscription&lt;br /&gt;
 Architectures: amd64&lt;br /&gt;
 Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg&lt;br /&gt;
 EOF&lt;br /&gt;
The &amp;quot;No-Nag&amp;quot; UI Patch: This command neutralizes the subscription check in the web interface and restarts the proxy service to apply it&lt;br /&gt;
 # 4. Remove &#039;No Valid Subscription&#039; Login Popup&lt;br /&gt;
 sed -Ezi.bak &amp;quot;s/(Ext.Msg.show\(\{\s+title: gettext\(\&#039;No valid sub)/void\(\{ \/\/\1/g&amp;quot; /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js &amp;amp;&amp;amp; systemctl restart pveproxy.service&lt;br /&gt;
When the system reboots open a new console window for the host. So we can do an update. Always use dist-upgrade for Proxmox to ensure kernel and dependency changes are handled correctly.&lt;br /&gt;
 # 5. Refresh and Upgrade&lt;br /&gt;
 apt update &amp;amp;&amp;amp; apt dist-upgrade -y&lt;br /&gt;
Summary of why we did this&lt;br /&gt;
* The .bak method: Instead of fighting sed patterns that might change, moving the files to .bak is a &amp;quot;bulletproof&amp;quot; way to ensure apt ignores them.&lt;br /&gt;
* Trixie Suites: Using Suites: trixie ensures you aren&#039;t pulling in old bookworm (Proxmox 8) packages that could destabilize your new Ryzen 5 build.&lt;br /&gt;
* The 63 Packages: Now that you&#039;ve run the update, those 63 packages are waiting. Running the dist-upgrade command above will install the latest 2026 security patches and hardware drivers.&lt;br /&gt;
&lt;br /&gt;
=====Ironwolf Pro Harddrive Setup=====&lt;br /&gt;
&lt;br /&gt;
Since we have already performed the dist-upgrade, the kernel is fresh and ready to handle the heavy I/O of those 14TB drives. We will set this up via the CLI to ensure we get the exact optimizations needed for a high-density vault. First, we must be 100% certain which device names (/dev/sdX) belong to the IronWolfs.&lt;br /&gt;
 lsblk -o NAME,SIZE,MODEL,SERIAL&lt;br /&gt;
Look for the three drives that show approximately 12.7T (the TiB equivalent of 14TB). Verify the Model says ST14000.... In this case they are&lt;br /&gt;
* sda  12.7T ST14000NE0008-2JK101    ZTM0D5FK&lt;br /&gt;
* sdb  12.7T ST14000NE0008-2H4101    ZL2EJCXX (this one has a partition sdb1 but we ignore it)&lt;br /&gt;
* sdc  12.7T ST14000NE0008-2JK101    ZTM0D5A0&lt;br /&gt;
The Clean Slate (Wipe the Labels) Run these commands to clear the old ZFS and EFI labels. This doesn&#039;t delete all of the old data (which takes hours), it just &amp;quot;un-formats&amp;quot; the start and end of the disks so ZFS sees them as new. It may not be necessary for all of the drives but certainly is for sdb as that has a partition on it&lt;br /&gt;
 # Wipe the ZFS labels specifically&lt;br /&gt;
 zpool labelclear -f /dev/sda&lt;br /&gt;
 zpool labelclear -f /dev/sdb&lt;br /&gt;
 zpool labelclear -f /dev/sdc&lt;br /&gt;
 # Wipe the partition tables entirely (the &amp;quot;Nuclear&amp;quot; option)&lt;br /&gt;
 wipefs -a /dev/sda&lt;br /&gt;
 wipefs -a /dev/sdb&lt;br /&gt;
 wipefs -a /dev/sdc&lt;br /&gt;
&lt;br /&gt;
The other drive is the 990 Pro SSD. Now we can create the ZFS Z1 Pool We will name the pool kiwipool. We are using ashift=12 for 4K sector alignment and atime=off to save the mechanical heads from unnecessary movement.&lt;br /&gt;
 zpool create -o ashift=12 kiwipool raidz1 /dev/sda /dev/sdb /dev/sdc&lt;br /&gt;
 # Apply optimizations&lt;br /&gt;
 zfs set compression=lz4 kiwipool &lt;br /&gt;
 zfs set atime=off kiwipool &lt;br /&gt;
 zfs set xattr=sa kiwipool &lt;br /&gt;
 zfs set recordsize=1M kiwipool &lt;br /&gt;
once that is done we can verify the pool is built with&lt;br /&gt;
 zpool status kiwipool&lt;br /&gt;
Next we need to make some datasets to keep the pool organised and not write anything to the root of kiwipool. Run thes commands&lt;br /&gt;
 zfs create kiwipool/PFK&lt;br /&gt;
 zfs create kiwipool/PFK/pdata&lt;br /&gt;
 zfs create kiwipool/PFK/pdata/KiwiHDs&lt;br /&gt;
 zfs create kiwipool/ISO&lt;br /&gt;
 zfs create kiwipool/PFK/backups&lt;br /&gt;
 zfs list &lt;br /&gt;
The zpool will show up in the webgui in Kiwi-&amp;gt;storage and kiwi-&amp;gt;zfs but not in the VM list on the left hand pane so they cannot be added to VMs yet. To make them available we run the command&lt;br /&gt;
 pvesm add zfspool KiwiHDs --pool kiwipool/PFK/pdata/KiwiHDs --content rootdir,images&lt;br /&gt;
 pvesm add dir KiwiISOs --path /kiwipool/ISO --content iso,vztmpl&lt;br /&gt;
 pvesm add dir KiwiBackups --path /kiwipool/PFK/backups --content backup&lt;br /&gt;
Now in the webgui there should be the drives for VM HDs, ISOs and backups&lt;br /&gt;
&lt;br /&gt;
=====Check and configure the WiFi=====&lt;br /&gt;
&lt;br /&gt;
Testing Wi-Fi on a Proxmox (Debian) host is a bit different than on a laptop because there is no &amp;quot;taskbar&amp;quot; to click. We have to do this through the CLI. First, let&#039;s see if Debian even sees the Wi-Fi card and has the drivers loaded.&lt;br /&gt;
 ip link&lt;br /&gt;
Look for: An interface starting with w (e.g., wlp2s0 or wlan0). If you don&#039;t see one the drivers might be missing or it&#039;s &amp;quot;Hard Blocked&amp;quot; in the BIOS. In this case The hardware check is a success. Your Wi-Fi card is identified as wlp5s0 (it did show up in the installer but it was ignored then ). The state is currently DOWN, which is expected since it hasn&#039;t been configured with your SSID or credentials yet. Because Proxmox is built for servers, it lacks a graphical Wi-Fi picker. We have to manually tell the background service (wpa_supplicant) how to talk to your router. at the same time install the wireless tools package.&lt;br /&gt;
 apt update &amp;amp;&amp;amp; apt install wpasupplicant wireless-tools -y&lt;br /&gt;
Instead of typing the Wi-Fi password in plain text, we’ll use a tool to generate a secure configuration block. Replace Your_SSID and Your_Password with your actual wireless AP details:&lt;br /&gt;
 wpa_passphrase &amp;quot;Your_SSID&amp;quot; &amp;quot;Your_Password&amp;quot; &amp;gt; /etc/wpa_supplicant/wpa_supplicant.conf&lt;br /&gt;
Now we can test the connection let&#039;s see if Kiwi can actually authenticate.&lt;br /&gt;
 wpa_supplicant -B -i wlp5s0 -c /etc/wpa_supplicant/wpa_supplicant.conf&lt;br /&gt;
Then wait a few seconds before checking the status with &lt;br /&gt;
 iw wlp5s0 link&lt;br /&gt;
Assuming it shows a connection we can make it permanent. To ensure the Wi-Fi comes up automatically on boot and acts as a secondary management port, we need to add it to the network interfaces file. Warning: Be very careful with the syntax here. Use this command to append the configuration to /etc/network/interfaces. cat &amp;lt;&amp;lt;EOF &amp;gt;&amp;gt; /etc/network/interfaces&lt;br /&gt;
 auto wlp5s0&lt;br /&gt;
 iface wlp5s0 inet static&lt;br /&gt;
         address 192.168.1.113/24&lt;br /&gt;
         wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
=====🌐 Networking &amp;amp; The &amp;quot;Wi-Fi Failover&amp;quot; Battle=====&lt;br /&gt;
&lt;br /&gt;
This section documents the attempt to create a reliable wireless &amp;quot;emergency backdoor.&amp;quot; The objective was to have the Wi-Fi (192.168.1.113) act as a secondary management port that remains accessible even if the 2.5G cable is pulled. The Problem was cuased by (Asymmetric Routing). Linux prefers the route with the lowest metric. Since the 2.5G wire has a metric of 10 and Wi-Fi has 100, pulling the cable caused a &amp;quot;Routing Black Hole&amp;quot;—Kiwi would receive requests via Wi-Fi but try to reply via the dead Ethernet cable.&lt;br /&gt;
&lt;br /&gt;
Several fixes were applied including&lt;br /&gt;
* Kernel Routing Tweaks: Added to /etc/sysctl.conf to force the OS to ignore dead routes immediately&lt;br /&gt;
 nano /etc/sysctl.conf&lt;br /&gt;
&lt;br /&gt;
 net.ipv4.conf.all.ignore_routes_with_linkdown=1&lt;br /&gt;
 net.ipv4.conf.default.ignore_routes_with_linkdown=1&lt;br /&gt;
 net.ipv4.conf.all.arp_ignore=1&lt;br /&gt;
 net.ipv4.conf.all.arp_announce=2&lt;br /&gt;
* We tried to create service persistence. We created a systemd override for wpa_supplicant@wlp5s0 to handle driver timing issues&lt;br /&gt;
 [Service]&lt;br /&gt;
 Restart=on-failure&lt;br /&gt;
 RestartSec=5s&lt;br /&gt;
 ExecStartPost=/usr/sbin/ifup wlp5s0 --force&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Proxmox_Server&amp;diff=1509</id>
		<title>Proxmox Server</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Proxmox_Server&amp;diff=1509"/>
		<updated>2026-05-01T04:35:25Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* 🌐Network Access */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==📋Introduction==&lt;br /&gt;
&lt;br /&gt;
This is the server that will sit under my desk until I move house. It has the hostname Pear and will be the beginning of the &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039;. There is also now a new smaller and less powerful server with the hostname Kiwi.&lt;br /&gt;
&lt;br /&gt;
==🥝[[Create Virtual Machine from a template]]==&lt;br /&gt;
&lt;br /&gt;
it is possible to create a new VM based on a fixed template. The two possibilities are a full clone or a linked clone. the linked clone is the preferred as it should need less storage but the full clone would be completely independent of the template so it will use more storage and take longer to create.We can go down that rabbit hole when we look ant Ansible in a big way. For now just understand that we can call a new vm  using the  qm clone command. the will be more details to follow.&lt;br /&gt;
&lt;br /&gt;
==Pear==&lt;br /&gt;
The first host has Proxmox installed with the following specificatio&lt;br /&gt;
&lt;br /&gt;
===🛠️Hardware Specification===&lt;br /&gt;
&lt;br /&gt;
The Main components were purchased in 2024 as follows&lt;br /&gt;
&lt;br /&gt;
* The Cpu is AMD Ryzen 9 5950X Processor (16Cores/32Threads, 105W TDP, Socket AM4, 72MB Cache, Up to 4.9 GHz Max Boost, no cooler) £369.98&lt;br /&gt;
* The cooler is Noctua NH-D15, Premium CPU Cooler with 2x NF-A15 PWM 140mm Fans (Brown) £99.95&lt;br /&gt;
* Mainboard is Gigabyte B550M AORUS ELITE Motherboard - Supports AMD Ryzen 5000 Series AM4 CPUs, 5+3 Phases Pure Digital VRM, up to 4733MHz DDR4 (OC), 2xPCIe 3.0 M.2, GbE LAN, USB 3.2 Gen1 £103.48&lt;br /&gt;
* 128gb Ram is configured as two sets of CORSAIR VENGEANCE LPX DDR4 RAM 64GB (2x32GB) 3200MHz CL16-20-20-38 1.35V (CMK64GX4M2E3200C16) £112.20 for one set&lt;br /&gt;
* GPU is a Gigabyte Geforce RTX 5060 TI with 16 GB Ram&lt;br /&gt;
* Power supply is Corsair RM750x 80 Plus Gold Fully Modular ATX 750 Watt Power Supply £109.00&lt;br /&gt;
* The case is Fractal Design Node 804 - Black - Compact Computer Case - mATX - High Airflow - Modular interior - 3x Fractal Design Silent R2 120mm Fans Included - Water-cooling ready - USB 3.0 -Window Side Panel £99.95 &lt;br /&gt;
* SSD is Crucial P3 Plus SSD 4TB M.2 NVMe PCIe Gen4 Internal SSD, Up to 4800MB/s, Laptop &amp;amp; Desktop (PC) Compatible, Solid State Drive - CT4000P3PSSD801 £189.99 and £159.99&lt;br /&gt;
* Three 16 TB Seagate Ironwolf NAS drives make up the hard disk storage at a cost of £179.94 each total £ 539.82.&lt;br /&gt;
* One cheap 1 TB SATA SSD currently set as a L2ARC but may reconfigure as a sacrificial drive for the high wear VMs if it looks like it is not getting many hits as L2ARC &#039;&#039;&#039;Update &#039;&#039;&#039; no longer used as L2ARC and formmated to a zpool fastpool.&lt;br /&gt;
&lt;br /&gt;
===Configuration===&lt;br /&gt;
&lt;br /&gt;
====🌐Network Access====&lt;br /&gt;
&lt;br /&gt;
The IP Address and port of the host is 192.168.0.110:8006. I have my virgin media router forwarding all incoming traffic to 192.168.0.125 so it will go directly to the Pfsense firewall. All of the terminals can also send traffic to the WAN port of Pfsense. &#039;&#039;&#039;Edit&#039;&#039;&#039; with the change to Vodaphone the network address changed to 192.168.1.0/24 so Proxmox console is now 192.168.1.111:8006 and the WAN port of Pfsense is 192.168.1.125. a further change was to only forward those ports that are actually needed to Pfsense because the new ISP router has better options than the really old Virgin media one ( to be fair if i had stayed with Virgin i would have got a newer router). More [[Network Configuration]] details.&lt;br /&gt;
&lt;br /&gt;
====💾Storage====&lt;br /&gt;
&lt;br /&gt;
The main storage is the three 16TB hard drives configure into ZFS z1 so that they have one redundant disk. As one disk is redundant, obviously, it has 32TB of storage available.&lt;br /&gt;
&lt;br /&gt;
I couldn&#039;t get PCI passthrough to work reliably without significant effort and some expense so I set up ZFS on Proxmox itself or more precisely on the Debian Linux that Proxmox resides on. Unfortunately, that means that I have to do any config on the CLI. I may write some scripts to perform some of the admin tasks or more likely setup a Nginx container to automate as much of it as possible. For the time being some useful ZFS commands can be found &#039;&#039;&#039;[[ZFS Commands |here]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==🥝 Kiwi Host: Technical Manual &amp;amp; Build Log==&lt;br /&gt;
&lt;br /&gt;
Kiwi is the secondary Proxmox host in the Home Lab, housed in a Fractal Design ITX chassis. While less powerful than the primary host (Pear), it serves as a high-capacity storage node and 2.5G data target.&lt;br /&gt;
&lt;br /&gt;
=== Hardware Specification ===&lt;br /&gt;
&lt;br /&gt;
* CPU: AMD Ryzen 5 with Stock Wraith Cooler.&lt;br /&gt;
* RAM: 64GB (2x32GB Crucial DDR4), maxing out the two available slots.&lt;br /&gt;
* System Drive: 2TB Samsung 990 Pro NVMe (Firmware verified: 5B2QJXD7).&lt;br /&gt;
* Storage Pool: 3x 14TB Seagate IronWolf Pro HDDs (ZFS RAIDZ1, 28TB usable).&lt;br /&gt;
* Network: Onboard 2.5 Gbps Wired NIC (nic0) + Built-in Wi-Fi (wlp5s0).&lt;br /&gt;
* GPU: Legacy Nvidia GPU (Required for POST and initial installation). The Mainboard has 4 SATA ports on board. Three of them have 14 TB Ironwolf pro drives to be formatted as a ZFS array with Z! so will give 28TB of usable storage with one disk of redundancy&lt;br /&gt;
&lt;br /&gt;
===Proxmox Installation===&lt;br /&gt;
&lt;br /&gt;
It is assumed that the Proxmox installer has been downloaded from their website and the iso has been copied on to a USB stick and made bootable with Rufus or some other similar. If the reader doesn&#039;t know how to make a USB installer from an ISO try typing &amp;quot;How do I make a USB stick into a proxmox installer&amp;quot; in to a browser. there will be loads of guides on how to use Rufus. When a bootable USB stick with Proxmox installer on it has been created insert in to one of the USB slots along with a keyboard, mouse and screen. Please note the keyboard mouse and screen will only be needed for the installation, once Proxmox is installed it is unlikely that these will ever be used again because virtually all administration is performed on a web GUI. &lt;br /&gt;
&lt;br /&gt;
====BIOS settings for Hypervisors (including Proxmox)====&lt;br /&gt;
&lt;br /&gt;
Generally most BIOS can be left at defaults and a PC as a PC will work well enough, maybe the boot priority may need to be changed from a HDD to a SSD but even that is unlikely. It is possible to optimise lots of things in BIOS and for some people that is an option but it is also easy to make mistakes that either stop the machine from working or making the machine unstable so for most people, most of the time, it is better to leave BIOS alone. A big exception is when a hypervisor is to be install because a few options that are off by default need to be set for Virtualisation to work properly. The main things to set are:-&lt;br /&gt;
* SVM Mode (AMD-V): &#039;&#039;&#039;Must be Enabled.&#039;&#039;&#039; This is what allows Proxmox to run VMs. Without it virtualisation will fail with most or possibly all hypervisors&lt;br /&gt;
* IOMMU: Set to Enabled. This is vital if you ever want to &amp;quot;pass through&amp;quot; a SATA controller or GPU directly to a VM. while not vital for the virtualisation itself most hypervisors have this enabled.&lt;br /&gt;
* Power Supply Idle Control: If you find the server randomly freezes when idle, set this to &amp;quot;Typical Current Idle&amp;quot;. Ryzen chips sometimes drop voltage too low for some power supplies when idling, causing a crash. Again not vital but a &amp;quot;nice to have&amp;quot; if possible in the BIOS.&lt;br /&gt;
* Boot options: The SSD should be at the top. It is better to set the USB at the bottom so that if a USB is left in the machine and it is rebooted it doesn&#039;t try to boot from the USB.&lt;br /&gt;
Once the BIOS option are set save the settings and quit. The computer will shutdown and restart, while it is restarting keep pressing the delete key or the F12 key to bring up the boot options (it is usually delete key but it should also display the options briefly on the screen as it starts). &lt;br /&gt;
&lt;br /&gt;
====GPU Considerations====&lt;br /&gt;
&lt;br /&gt;
The Proxmox installation is a little bit more tricky than is standard for the majority of computers in that this has an old GPU that the installer does not recognise. A GPU is required so that the machine will pass POST but is not really need or used by the Proxmox guests so is generally of little benefit for the overall Proxmox day to day running. A lot of Hypervisor hosts have the cheapest and lowest power GPUs installed just enough to POST but no more than that. The reason that GPU is of low priorty for most hypervisors hosts is that they are generally run headless, that is without a monitor attached, all interations with the host is through a dedicated application like Citrix XEN, or more likely through a web browser like Proxmox. Web based GUIs are popular because it is a lot easier and lighter processor load to have a webserver attached than it is to design a whole application. Kiwi has an old Nvidia GPU that works in that it provides a display but that is about it. Unfortunately, it does give some problems for the installer as it is so old but therea re steps to overcome that as will be detailed below. We may add a bigger and better GPU at a later date but for the foreseeable future that is in the realms of an upgrade for later and dependant on inheriting a GPU from another box.&lt;br /&gt;
&lt;br /&gt;
====Proxmox Installer problems (The Kiwi exceptions)====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As stated earlier the Proxmox installer does not work with the GPU. This is shown in that the machine boots and loads the first screen of the installer with welcome to.. but when the first option is tried it starts to load then freezes at the loading Nvidia drivers or some such thing(cant remember exactly what it says). so to fix that issue we need to restart the host and when we get to the welcome screen again we highlight &amp;quot;Install Proxmox VE (Graphical)&amp;quot; but &#039;&#039;&#039;do not press Enter&#039;&#039;&#039; instead we press &amp;quot;e&amp;quot; so a black screen with GNU GRUB appears. Edit the line&lt;br /&gt;
 linux /boot/linux26 ro ramdisk_size=16777216 rw quiet splash=silent&lt;br /&gt;
so it reads &lt;br /&gt;
 linux /boot/linux26 ro ramdisk_size=16777216 rw nomodeset&lt;br /&gt;
* By removing the quiet splash=silent we force the installer to show every single line of code as it loads. If it freezes again, we see the exact driver name where it stopped (e.g., sata_nv or i915).&lt;br /&gt;
* Adding nomodeset: This is the &amp;quot;magic bullet&amp;quot; for the nvidiafb hang. It tells the kernel not to touch the video drivers until the system is fully loaded. It is most likely where the installer hangs. As we should see every line of the execution of the installer if we have a different driver issue we should still see it.&lt;br /&gt;
To save the changes press ctrl+x or maybe F10. The GNU Grub screen will close and the graphical installer will continue until it gets to the &amp;quot;end user license agreement (EULA) screen. For anyone else reading this, If  the installer freezes again before it gets to the EULA screen the error will most likely be in the last laine of text displayed. The most likely error will be a conflict between Debian kernel and Advanced Configuration and Power Interface (ACPI) in which case restart and press the &amp;quot;e&amp;quot; to get to the Grub config and edit the same line &lt;br /&gt;
 linux /boot/linux26 ro ramdisk_size=16777216 rw nomodeset&lt;br /&gt;
so that it now has noapic added. note that this is just for the installer not the Proxmox application. &lt;br /&gt;
 linux /boot/linux26 ro ramdisk_size=16777216 rw nomodeset noapic&lt;br /&gt;
After modifying that line press ctrl+x or F10 to save and proceed. if it stalls again you will need to look for the exact error in the last line or last few lines that the installer performed or any line that starts or ends with failed.&lt;br /&gt;
&lt;br /&gt;
====Proxmox installer continued====&lt;br /&gt;
&lt;br /&gt;
After the earlier problems we should have got to the ELUA screen so press &amp;quot;I agree&amp;quot; button to continue. The next screen will be about choosing hard drives. Kiwi has a single SSD and three Ironwolf Pro 14 TB HDDs. Obviously, we will not install the OS onto a HDD or even all three HDDs as it would be too slow and as the SSD is fast we will choose that as the Target Harddisk. with the SSD selected click on options button.&lt;br /&gt;
* select zfs (RAID0) &lt;br /&gt;
* select samsung SSD as hardisk 0&lt;br /&gt;
* select Do not use for harddisk 1&lt;br /&gt;
* select Do not use for harddisk 2&lt;br /&gt;
* select Do not use for harddisk 3&lt;br /&gt;
ZFS is the best choice as it has native compression, Bitrot detection but not really protection because there is only one drive so nowhere to restore any corrupt data from. ZFS also has good snapshot capability. Ext4 / XFS are &amp;quot;set it and forget it&amp;quot; options. They use almost zero RAM, but they offer no protection against data corruption and have very basic snapshotting capabilities (via LVM).  Btrfs is similar to ZFS but generally considered less stable and has a lower feature set. The HDDs will not be used during the installation of Proxmox because it is easier to set them up from within the Proxmox web GUI or CLI.so the do not use is the best option for now &#039;&#039;&#039;note&#039;&#039;&#039; before we exit the Harddisk Options we need to check that the &#039;&#039;&#039;ashift&#039;&#039;&#039; is set to 12 so that the data blocks align with the physical page size of the Samsung 990 Pro&#039;s NAND, ensuring maximum speed, so select Advanced Options button next to Disk setup. Choose&lt;br /&gt;
* ashift is 12&lt;br /&gt;
* compress is on&lt;br /&gt;
* checksum is on&lt;br /&gt;
* copies is 1. Since this is a single-disk ZFS RAID0, copies=1 is the standard. If it is set it to 2, it would store every block twice on the same physical SSD. While that would allow ZFS to repair bitrot, it would effectively cut the 2TB SSD down to 1TB and halve the write speeds. With a 990 Pro, standard checksums and a good backup strategy are much more efficient.&lt;br /&gt;
* ARC max size 6422 Since there are only have two RAM slots and we are capped at 64GB, we need to be very intentional about how we carve up Kiwi RAM. having said that it is only a Maximum not a set size and zfs does not have to use all of it&#039;s maximum&lt;br /&gt;
* hdsize is set to maximum ( the + button will only allow it to be the size of the harddisk so click it until it stops going up)&lt;br /&gt;
Check the settings and when all looks correct click next for the regional settings&lt;br /&gt;
* Country United Kingdom&lt;br /&gt;
* Timezone Europe/London (or UTC if preferred)&lt;br /&gt;
* Keyboard Layout United Kingdom&lt;br /&gt;
Then next to set password and email address screen. Set a strong password that you can remember for the administration of the host. If the password is lost it will be almost impossible to recover it so do not forget it. Also it will be the hackers dream to get hold of the Proxmox host&#039;s password in that all of the rest of the security is mainly built on top of the administration of the host. If a host in a cluster is compromised it is quite likely that the whole cluster is compromised. The email address is so Proxmox can send promotional or updates but in general they don&#039;t flood their users with spam so it is no problem adding in a real email address. When done Click next to se the Management Network configuration screen.&lt;br /&gt;
&lt;br /&gt;
The Management Network Configuration will determine where the WebGUI will be presented from. Kiwi has two NICs, one is the 2.5 GB p/s wired NIC and the other is the wireless NIC. by default it is likely to be the wired NIC that is going to be the one used for the management interface, mainly because at this stage WiFi has not been set up yet. Set up the options as follows&lt;br /&gt;
* Management Interface nic0 (the r8169 is the driver that Debian uses for wired nics) It is the one that is up and the Wifi nic is down so it is straight forward to establish which is which.&lt;br /&gt;
* hostname will be kiwi.seaoffate.net it is safe for us to use this domain name because we have registered it. If the reader has no domain name it could be kiwi.local but it would be unwise to use something that is already register on the public Internet, it may appear to work but there will be odd unforeseen problems like getting updates or push notifications or some other odd thing that don&#039;t work because the reply is being sent to a different IP address.&lt;br /&gt;
* IP address will be 192.168.1.112/24&lt;br /&gt;
* Gateway will be 192.168.1.1&lt;br /&gt;
* DNS will be 192.168.1.1&lt;br /&gt;
When this is done click next for the Summary. Make sure it is all correct and the auto reboot after successful installation then click install.&lt;br /&gt;
&lt;br /&gt;
====Post Installation ====&lt;br /&gt;
&lt;br /&gt;
When the host finishes the install it will restart. It may show the Proxmox Intallation again if the USB is still plugged in depending on the boot options, if so remove the USB and restart the computer. once the computer has finished starting it should show a simple login screen with the web address that is the main administration panel. from this point on the screen, mouse and keyboard can and should be removed as they will probably be never be used again. Now Kiwi will be managed from a web browser. The address will be whatever was set in the Management Network Configuration section with the port number 8006. in the case of Kiwi it is http://192.168.1.112:8006 the browser will give a security warning as no SSL cert has been setup for it yet so click advanced or ignore or whatever the browser needs to get to the web address. Then there will be a bank Proxmox screen with a popup in the middle with the title Proxmox VE Login the login details are&lt;br /&gt;
* Username root&lt;br /&gt;
* Password your_password  ( whatever was set in the password and email section of the instalation)&lt;br /&gt;
* Realm is Linux PAM standard authentication&lt;br /&gt;
* Language English - English&lt;br /&gt;
&#039;&#039;&#039;note&#039;&#039;&#039; username and password are case sensitive&lt;br /&gt;
&lt;br /&gt;
=====Samsung 990 Pro series SSDs Firmware=====&lt;br /&gt;
Now we have logged in we need to check that the Samsung SSD has got up to date firmware, &#039;&#039;&#039;Note This is for Samsung 990 Pro SSDs&#039;&#039;&#039; and not all SSDs it is not even all Samsung SSDs just this particular model in the early versions. Select Kiwi from the left pane then towards the top right of the main pane there is a row of buttons reboot, shutdown, shell, bulk actions, and help click on shell. A new window will appear with root@kiwi already logged in. Type the following into the window&lt;br /&gt;
  smartctl -a /dev/nvme0n1&lt;br /&gt;
look through the information for the SSD, under === START OF INFORMATION SECTION === it should have a firmware Version line. Make sure the version is not &amp;quot;1B2QJXD7&amp;quot; it should be safe if it starts with 3 or more. If the  Samsung 990 Pro SSD does have the unsafe version stop now and update the firmware immediately or it is likely that it will stop working after a short time. The version on this host is Firmware Version: 5B2QJXD7&lt;br /&gt;
&lt;br /&gt;
=====Fix the No Subscription nag and do system update=====&lt;br /&gt;
By default, Proxmox tries to use a paid repository that you can&#039;t access. We need to disable that and add the free community one. This assumes that it is Proxmox version 9.x. Proxmox 9 uses .sources files. We must disable the default enterprise links and add the community repository. Run these commands in the Kiwi shell&lt;br /&gt;
 # 1. Disable Enterprise PVE Repo&lt;br /&gt;
 mv /etc/apt/sources.list.d/pve-enterprise.sources /etc/apt/sources.list.d/pve-enterprise.sources.bak&lt;br /&gt;
 # 2. Disable Enterprise Ceph Repo&lt;br /&gt;
 mv /etc/apt/sources.list.d/ceph.sources /etc/apt/sources.list.d/ceph.sources.bak&lt;br /&gt;
 # 3. Create the No-Subscription Source&lt;br /&gt;
 cat &amp;lt;&amp;lt;EOF &amp;gt; /etc/apt/sources.list.d/pve-no-subscription.sources&lt;br /&gt;
 Types: deb&lt;br /&gt;
 URIs: http://download.proxmox.com/debian/pve&lt;br /&gt;
 Suites: trixie&lt;br /&gt;
 Components: pve-no-subscription&lt;br /&gt;
 Architectures: amd64&lt;br /&gt;
 Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg&lt;br /&gt;
 EOF&lt;br /&gt;
The &amp;quot;No-Nag&amp;quot; UI Patch: This command neutralizes the subscription check in the web interface and restarts the proxy service to apply it&lt;br /&gt;
 # 4. Remove &#039;No Valid Subscription&#039; Login Popup&lt;br /&gt;
 sed -Ezi.bak &amp;quot;s/(Ext.Msg.show\(\{\s+title: gettext\(\&#039;No valid sub)/void\(\{ \/\/\1/g&amp;quot; /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js &amp;amp;&amp;amp; systemctl restart pveproxy.service&lt;br /&gt;
When the system reboots open a new console window for the host. So we can do an update. Always use dist-upgrade for Proxmox to ensure kernel and dependency changes are handled correctly.&lt;br /&gt;
 # 5. Refresh and Upgrade&lt;br /&gt;
 apt update &amp;amp;&amp;amp; apt dist-upgrade -y&lt;br /&gt;
Summary of why we did this&lt;br /&gt;
* The .bak method: Instead of fighting sed patterns that might change, moving the files to .bak is a &amp;quot;bulletproof&amp;quot; way to ensure apt ignores them.&lt;br /&gt;
* Trixie Suites: Using Suites: trixie ensures you aren&#039;t pulling in old bookworm (Proxmox 8) packages that could destabilize your new Ryzen 5 build.&lt;br /&gt;
* The 63 Packages: Now that you&#039;ve run the update, those 63 packages are waiting. Running the dist-upgrade command above will install the latest 2026 security patches and hardware drivers.&lt;br /&gt;
&lt;br /&gt;
=====Ironwolf Pro Harddrive Setup=====&lt;br /&gt;
&lt;br /&gt;
Since we have already performed the dist-upgrade, the kernel is fresh and ready to handle the heavy I/O of those 14TB drives. We will set this up via the CLI to ensure we get the exact optimizations needed for a high-density vault. First, we must be 100% certain which device names (/dev/sdX) belong to the IronWolfs.&lt;br /&gt;
 lsblk -o NAME,SIZE,MODEL,SERIAL&lt;br /&gt;
Look for the three drives that show approximately 12.7T (the TiB equivalent of 14TB). Verify the Model says ST14000.... In this case they are&lt;br /&gt;
* sda  12.7T ST14000NE0008-2JK101    ZTM0D5FK&lt;br /&gt;
* sdb  12.7T ST14000NE0008-2H4101    ZL2EJCXX (this one has a partition sdb1 but we ignore it)&lt;br /&gt;
* sdc  12.7T ST14000NE0008-2JK101    ZTM0D5A0&lt;br /&gt;
The Clean Slate (Wipe the Labels) Run these commands to clear the old ZFS and EFI labels. This doesn&#039;t delete all of the old data (which takes hours), it just &amp;quot;un-formats&amp;quot; the start and end of the disks so ZFS sees them as new. It may not be necessary for all of the drives but certainly is for sdb as that has a partition on it&lt;br /&gt;
 # Wipe the ZFS labels specifically&lt;br /&gt;
 zpool labelclear -f /dev/sda&lt;br /&gt;
 zpool labelclear -f /dev/sdb&lt;br /&gt;
 zpool labelclear -f /dev/sdc&lt;br /&gt;
 # Wipe the partition tables entirely (the &amp;quot;Nuclear&amp;quot; option)&lt;br /&gt;
 wipefs -a /dev/sda&lt;br /&gt;
 wipefs -a /dev/sdb&lt;br /&gt;
 wipefs -a /dev/sdc&lt;br /&gt;
&lt;br /&gt;
The other drive is the 990 Pro SSD. Now we can create the ZFS Z1 Pool We will name the pool kiwipool. We are using ashift=12 for 4K sector alignment and atime=off to save the mechanical heads from unnecessary movement.&lt;br /&gt;
 zpool create -o ashift=12 kiwipool raidz1 /dev/sda /dev/sdb /dev/sdc&lt;br /&gt;
 # Apply optimizations&lt;br /&gt;
 zfs set compression=lz4 kiwipool &lt;br /&gt;
 zfs set atime=off kiwipool &lt;br /&gt;
 zfs set xattr=sa kiwipool &lt;br /&gt;
 zfs set recordsize=1M kiwipool &lt;br /&gt;
once that is done we can verify the pool is built with&lt;br /&gt;
 zpool status kiwipool&lt;br /&gt;
Next we need to make some datasets to keep the pool organised and not write anything to the root of kiwipool. Run thes commands&lt;br /&gt;
 zfs create kiwipool/PFK&lt;br /&gt;
 zfs create kiwipool/PFK/pdata&lt;br /&gt;
 zfs create kiwipool/PFK/pdata/KiwiHDs&lt;br /&gt;
 zfs create kiwipool/ISO&lt;br /&gt;
 zfs create kiwipool/PFK/backups&lt;br /&gt;
 zfs list &lt;br /&gt;
The zpool will show up in the webgui in Kiwi-&amp;gt;storage and kiwi-&amp;gt;zfs but not in the VM list on the left hand pane so they cannot be added to VMs yet. To make them available we run the command&lt;br /&gt;
 pvesm add zfspool KiwiHDs --pool kiwipool/PFK/pdata/KiwiHDs --content rootdir,images&lt;br /&gt;
 pvesm add dir KiwiISOs --path /kiwipool/ISO --content iso,vztmpl&lt;br /&gt;
 pvesm add dir KiwiBackups --path /kiwipool/PFK/backups --content backup&lt;br /&gt;
Now in the webgui there should be the drives for VM HDs, ISOs and backups&lt;br /&gt;
&lt;br /&gt;
=====Check and configure the WiFi=====&lt;br /&gt;
&lt;br /&gt;
Testing Wi-Fi on a Proxmox (Debian) host is a bit different than on a laptop because there is no &amp;quot;taskbar&amp;quot; to click. We have to do this through the CLI. First, let&#039;s see if Debian even sees the Wi-Fi card and has the drivers loaded.&lt;br /&gt;
 ip link&lt;br /&gt;
Look for: An interface starting with w (e.g., wlp2s0 or wlan0). If you don&#039;t see one the drivers might be missing or it&#039;s &amp;quot;Hard Blocked&amp;quot; in the BIOS. In this case The hardware check is a success. Your Wi-Fi card is identified as wlp5s0 (it did show up in the installer but it was ignored then ). The state is currently DOWN, which is expected since it hasn&#039;t been configured with your SSID or credentials yet. Because Proxmox is built for servers, it lacks a graphical Wi-Fi picker. We have to manually tell the background service (wpa_supplicant) how to talk to your router. at the same time install the wireless tools package.&lt;br /&gt;
 apt update &amp;amp;&amp;amp; apt install wpasupplicant wireless-tools -y&lt;br /&gt;
Instead of typing the Wi-Fi password in plain text, we’ll use a tool to generate a secure configuration block. Replace Your_SSID and Your_Password with your actual wireless AP details:&lt;br /&gt;
 wpa_passphrase &amp;quot;Your_SSID&amp;quot; &amp;quot;Your_Password&amp;quot; &amp;gt; /etc/wpa_supplicant/wpa_supplicant.conf&lt;br /&gt;
Now we can test the connection let&#039;s see if Kiwi can actually authenticate.&lt;br /&gt;
 wpa_supplicant -B -i wlp5s0 -c /etc/wpa_supplicant/wpa_supplicant.conf&lt;br /&gt;
Then wait a few seconds before checking the status with &lt;br /&gt;
 iw wlp5s0 link&lt;br /&gt;
Assuming it shows a connection we can make it permanent. To ensure the Wi-Fi comes up automatically on boot and acts as a secondary management port, we need to add it to the network interfaces file. Warning: Be very careful with the syntax here. Use this command to append the configuration to /etc/network/interfaces. cat &amp;lt;&amp;lt;EOF &amp;gt;&amp;gt; /etc/network/interfaces&lt;br /&gt;
 auto wlp5s0&lt;br /&gt;
 iface wlp5s0 inet static&lt;br /&gt;
         address 192.168.1.113/24&lt;br /&gt;
         wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
=====🌐 Networking &amp;amp; The &amp;quot;Wi-Fi Failover&amp;quot; Battle=====&lt;br /&gt;
&lt;br /&gt;
This section documents the attempt to create a reliable wireless &amp;quot;emergency backdoor.&amp;quot; The objective was to have the Wi-Fi (192.168.1.113) act as a secondary management port that remains accessible even if the 2.5G cable is pulled. The Problem was cuased by (Asymmetric Routing). Linux prefers the route with the lowest metric. Since the 2.5G wire has a metric of 10 and Wi-Fi has 100, pulling the cable caused a &amp;quot;Routing Black Hole&amp;quot;—Kiwi would receive requests via Wi-Fi but try to reply via the dead Ethernet cable.&lt;br /&gt;
&lt;br /&gt;
Several fixes were applied including&lt;br /&gt;
* Kernel Routing Tweaks: Added to /etc/sysctl.conf to force the OS to ignore dead routes immediately&lt;br /&gt;
 nano /etc/sysctl.conf&lt;br /&gt;
&lt;br /&gt;
 net.ipv4.conf.all.ignore_routes_with_linkdown=1&lt;br /&gt;
 net.ipv4.conf.default.ignore_routes_with_linkdown=1&lt;br /&gt;
 net.ipv4.conf.all.arp_ignore=1&lt;br /&gt;
 net.ipv4.conf.all.arp_announce=2&lt;br /&gt;
* We tried to create service persistence. We created a systemd override for wpa_supplicant@wlp5s0 to handle driver timing issues&lt;br /&gt;
 [Service]&lt;br /&gt;
 Restart=on-failure&lt;br /&gt;
 RestartSec=5s&lt;br /&gt;
 ExecStartPost=/usr/sbin/ifup wlp5s0 --force&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=The_Kiwix_Archive&amp;diff=1508</id>
		<title>The Kiwix Archive</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=The_Kiwix_Archive&amp;diff=1508"/>
		<updated>2026-04-20T20:29:48Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* 📖 Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==📖 Introduction==&lt;br /&gt;
Kiwix is an offline content reader that allows you to browse massive websites—like Wikipedia, StackExchange, or Project Gutenberg—without an internet connection.&lt;br /&gt;
* The Format: It uses highly compressed .ZIM files. A single file can contain the entirety of Wikipedia (with images) or the complete medical encyclopedia.&lt;br /&gt;
* The Goal: To provide a permanent, offline knowledge base that remains accessible even if the internet is down, serving everyone on your local network.&lt;br /&gt;
* Synergy: Works alongside &#039;&#039;&#039;[[OpenAlex]]&#039;&#039;&#039; (scholarly search) and &#039;&#039;&#039;[[The Web Archive (ArchiveBox) | ArchiveBox]]&#039;&#039;&#039; (personal web snapshots) to create a three-tier local research library.&lt;br /&gt;
&lt;br /&gt;
Once this collection of Zims are downloaded we can also extract the text from the files to create a collection of .MD files which can then be used as a Retrieval-Augmented Generation database or RAG database for offline LLMs or the same data could be used as fine tuning data for o0ne or more LLMs. Although some of the .MDs will be general knowledge and only really useful for the RAG DB some will detailed question and answer tables of condensed information for example the Slack Overflow will be high density data sets&lt;br /&gt;
&lt;br /&gt;
==💾 The Infrastructure ==&lt;br /&gt;
Blackberry has been slimmed down to be more efficient now that indexing is handled elsewhere.&lt;br /&gt;
* Host: Blackberry&lt;br /&gt;
* VM Config: Debian | 4 Cores | 6GB RAM.&lt;br /&gt;
* Storage: 4TB XFS disk mounted at /mnt/docker_data and an additional 5TB XFS disk for ArchiveBox /mnt/archive_data&lt;br /&gt;
&lt;br /&gt;
==[[Linux Commands]]==&lt;br /&gt;
&lt;br /&gt;
A set of Linux commands to help show the progress of indexing and file copying&lt;br /&gt;
&lt;br /&gt;
==🐋 The Software Stack (Docker)==&lt;br /&gt;
&lt;br /&gt;
=== Installing Docker &amp;amp; Compose=== &lt;br /&gt;
&lt;br /&gt;
Before installing Dockge, we must install the Docker engine and the Compose plugin officially on Debian.&lt;br /&gt;
 # Update and install dependencies&lt;br /&gt;
 sudo apt update &amp;amp;&amp;amp; sudo apt install -y ca-certificates curl gnupg&lt;br /&gt;
 # Add Docker’s official GPG key&lt;br /&gt;
 sudo install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
 sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc&lt;br /&gt;
 sudo chmod a+r /etc/apt/keyrings/docker.asc&lt;br /&gt;
 # Add the repository to Apt sources&lt;br /&gt;
 echo \&lt;br /&gt;
   &amp;quot;deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \&lt;br /&gt;
   $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;$VERSION_CODENAME&amp;quot;) stable&amp;quot; | \&lt;br /&gt;
   sudo tee /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null&lt;br /&gt;
 # Install Docker Engine and Compose Plugin&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
 # Optional: Allow your user to run docker without sudo&lt;br /&gt;
 sudo usermod -aG docker $USER&lt;br /&gt;
&lt;br /&gt;
===🛠️  Installing Dockge===&lt;br /&gt;
Dockge allows us to manage our &amp;quot;Stacks&amp;quot; (Docker Compose files) through a clean web interface.&lt;br /&gt;
 # Preparation: Create directories&lt;br /&gt;
 mkdir -p /opt/stacks /opt/dockge&lt;br /&gt;
 cd /opt/dockge&lt;br /&gt;
 # Download and Start Dockge&lt;br /&gt;
 curl https://raw.githubusercontent.com/louislam/dockge/master/compose.yaml --output compose.yaml&lt;br /&gt;
 docker compose up -d&lt;br /&gt;
&lt;br /&gt;
===🛠️ Preparation: Storage Folders===&lt;br /&gt;
Organize The ZIM files on the 5TB disk so the container can find them easily.&lt;br /&gt;
 mkdir -p /mnt/docker_data/stacks/kiwix-archive/zim/&lt;br /&gt;
&lt;br /&gt;
===📄 Kiwix YAML (The Stack) ===&lt;br /&gt;
Deploy this in your Dockge instance on Blackberry (Port 5001) and name it kiwix&lt;br /&gt;
&lt;br /&gt;
 services:&lt;br /&gt;
   kiwix:&lt;br /&gt;
     image: ghcr.io/kiwix/kiwix-serve:latest&lt;br /&gt;
     container_name: kiwix_wikipedia&lt;br /&gt;
     volumes:&lt;br /&gt;
       - /mnt/docker_data/stacks/kiwix-archive/zim:/data&lt;br /&gt;
     ports:&lt;br /&gt;
       - 8081:8080&lt;br /&gt;
     command:&lt;br /&gt;
       - --library&lt;br /&gt;
       - library.xml&lt;br /&gt;
     restart: unless-stopped&lt;br /&gt;
 networks: {}&lt;br /&gt;
&lt;br /&gt;
===🌐 Accessing and Using the Library===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! Tool !! URL !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
|Kiwix Web UI || http://blackberry:8080 || Browsing your downloaded offline libraries.&lt;br /&gt;
|-&lt;br /&gt;
|ZIM Library || https://kiwix.org/en/download || Where to download new content (Wikipedia, StackOverflow, etc.).&lt;br /&gt;
|-&lt;br /&gt;
| German Zim Library || https://ftp.fau.de/kiwix/zim/ || lists of zim files.&lt;br /&gt;
|-&lt;br /&gt;
| Kewix org || https://download.kiwix.org/zim/ || More Lists of Zim files&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Indexing Files after download===&lt;br /&gt;
&lt;br /&gt;
There are three helper scripts in the /mnt/docker_data/stacks/kiwix-archive/zim/ directory that will help add new zim files to the xml index&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! Filename !!  Purpose&lt;br /&gt;
|-&lt;br /&gt;
|./audit_incomplete.sh || scans zim dir for incomplete files and move them to incomplete directory&lt;br /&gt;
|-&lt;br /&gt;
|./sweep_parts.sh || Checks any files in the incomplete directory for files that have corresponding completed downloaded Zim &lt;br /&gt;
|-&lt;br /&gt;
|./index_vault.sh || Adds new Zim to XML index file&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=AI_%26_Jellyfin&amp;diff=1507</id>
		<title>AI &amp; Jellyfin</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=AI_%26_Jellyfin&amp;diff=1507"/>
		<updated>2026-04-20T18:53:06Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Jellyfin Installation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
The objective for Quince is to make it the power house Virtual Machine for the AI so it needs to have the [[Linux Docker And GPU Passthrough | Nvidia 5060TI GPU passthrough ]] completed . At the same time it will also run a media server in the form of Jellyfin so that the GPU can do the transcoding. With the AI being serviced by this host we can use &#039;&#039;&#039;[[Data Archive | Blackberry]]&#039;&#039;&#039; for the Data Harvesting.&lt;br /&gt;
&lt;br /&gt;
== Docker Applications installed on Quince ==&lt;br /&gt;
&lt;br /&gt;
We are going to need to install several applications that will share the GPU. The first will be Dockge so that any new containers can be managed easily. We will also need to install Ollama so that we can run LLMs easily. Then to make use of the data archive we can use AnythingLLM.&lt;br /&gt;
&lt;br /&gt;
==Installation Strategy==&lt;br /&gt;
&lt;br /&gt;
Once the Blackwell GPU passthrough was verified on the Pear host, we transitioned to the Quince VM to set up the containerized environment. This allows us to run high-performance AI (Ollama) and media (Jellyfin) apps while keeping the base OS clean.&lt;br /&gt;
&lt;br /&gt;
===Docker Engine Installation===&lt;br /&gt;
&lt;br /&gt;
We use the official Docker repository to ensure access to v29+, which includes critical patches for Gen 5 PCIe and Blackwell architecture support.&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt install ca-certificates curl gnupg&lt;br /&gt;
Then setup the repository&lt;br /&gt;
 sudo install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg&lt;br /&gt;
 sudo chmod a+r /etc/apt/keyrings/docker.gpg&lt;br /&gt;
 echo &amp;quot;deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;$VERSION_CODENAME&amp;quot;) stable&amp;quot; | sudo tee /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null&lt;br /&gt;
Next Install Engine &amp;amp; Compose&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
===NVIDIA Container Toolkit (The &amp;quot;Magic Bridge&amp;quot;)===&lt;br /&gt;
This toolkit enables the libnvidia-container library, which maps the physical GPU device files (/dev/nvidia0, etc.) into the virtualized Docker namespace.&lt;br /&gt;
 curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
 curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
and last we configure the Nvidia Container tool Kit and restart Docker&lt;br /&gt;
 sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
 sudo systemctl restart docker&lt;br /&gt;
&lt;br /&gt;
==Docker Applications==&lt;br /&gt;
&lt;br /&gt;
===Dockge Setup===&lt;br /&gt;
Now that docker is installed we can install Dockge. To get Dockge running on Quince, we followed a specific path that keeps it isolated but powerful enough to manage your other stacks (Jellyfin, AnythingLLM, etc.).&lt;br /&gt;
Since Dockge is a &amp;quot;Docker manager that runs inside Docker,&amp;quot; the installation is a bit like a &amp;quot;Inception&amp;quot; move, we create a directory for it, and then use a simple script or a compose.yaml to launch it. &lt;br /&gt;
* Create the Directory Structure On Quince, we created a dedicated space for Dockge and all the future stacks you&#039;ll build. open a terminal and run the following &lt;br /&gt;
 mkdir -p /mnt/docker_data/dockge /mnt/docker_data/stacks&lt;br /&gt;
 cd /mnt/docker_data/dockge&lt;br /&gt;
* Download the Compose File We pulled the official configuration. Dockge needs access to the Docker Socket (/var/run/docker.sock) so it can &amp;quot;reach out&amp;quot; and control the other containers on Quince.&lt;br /&gt;
 curl https://raw.githubusercontent.com/louislam/dockge/master/compose.yaml --output compose.yaml&lt;br /&gt;
* Launch Dockge We started it up in &amp;quot;detached&amp;quot; mode.&lt;br /&gt;
 docker compose up -d&lt;br /&gt;
Now that Dockge is running we have a web interface on Quince:5001 and we can use it to add new services.&lt;br /&gt;
&lt;br /&gt;
===Jellyfin Installation===&lt;br /&gt;
&lt;br /&gt;
To give the media server plenty of storage we have mounted a 3TB data drive at /mnt/jellyfin/ to store all of the media files, we have another drive at /mnt/docker_data to hold all of the configuration data for the containers. We had some difficulty with a left over jellyfin container instalation so we called this container jellyfin-new to start with. The yaml file for &amp;quot;jellyfin-new&amp;quot; is as follows.&lt;br /&gt;
&lt;br /&gt;
 services:&lt;br /&gt;
   jellyfin:&lt;br /&gt;
     image: jellyfin/jellyfin&lt;br /&gt;
     container_name: jellyfin&lt;br /&gt;
     user: 1000:1000&lt;br /&gt;
     # ADD THIS SECTION:&lt;br /&gt;
     runtime: nvidia # Tells Docker to use the NVIDIA Container Toolkit&lt;br /&gt;
     deploy:&lt;br /&gt;
       resources:&lt;br /&gt;
         reservations:&lt;br /&gt;
           devices:&lt;br /&gt;
             - driver: nvidia&lt;br /&gt;
               count: 1&lt;br /&gt;
               capabilities: [gpu, video] # Grants access to NVENC/NVDEC&lt;br /&gt;
     ports:&lt;br /&gt;
       - 8096:8096&lt;br /&gt;
     volumes:&lt;br /&gt;
       - /mnt/docker_data/jellyfin/config:/config&lt;br /&gt;
       - /mnt/docker_data/jellyfin/cache:/cache&lt;br /&gt;
       - /mnt/jellyfin/audiobooks:/data/audiobooks&lt;br /&gt;
       - /mnt/jellyfin/oldfilms:/data/movies&lt;br /&gt;
       - /mnt/jellyfin/oldseries:/data/tvshows&lt;br /&gt;
       - /mnt/jellyfin/dji:/data/dji&lt;br /&gt;
     restart: unless-stopped&lt;br /&gt;
 networks: {}&lt;br /&gt;
&lt;br /&gt;
The web interface for Jellyfin is on port 8096 so http://quince:8096 will bring it up. To setup the local devices either with a webrowser or the Jellyfin Media player the firewall will forward 8096 to the media server.&lt;br /&gt;
* To use the Nvidia Toolkit with jellyfin we set the device driver to nvidia in the yaml file.&lt;br /&gt;
* After clicking &amp;quot;Deploy&amp;quot; in Dockge, we can verified the container could &amp;quot;talk&amp;quot; to the 5060 Ti with the command&lt;br /&gt;
 docker exec -it jellyfin nvidia-smi&lt;br /&gt;
We should have an output with the line something like &lt;br /&gt;
 NVIDIA-SMI 580.126.09             Driver Version: 580.126.09     CUDA Version: 13.0 &lt;br /&gt;
====Post-Install Playback Optimization====&lt;br /&gt;
Inside the Jellyfin Web UI (Dashboard &amp;gt; Playback), we have enabled Nvidia NVENC and checked the following critical Blackwell features:&lt;br /&gt;
* Hardware Decoding: H264, HEVC, AV1, VP9.&lt;br /&gt;
* AV1 Encoding: Allowed (The 5060 Ti is one of the few cards that can do this, significantly saving bandwidth).&lt;br /&gt;
* Tone Mapping: Enabled (Necessary for playing 4K HDR DJI drone footage on SDR screens).&lt;br /&gt;
&lt;br /&gt;
===AI applications ===&lt;br /&gt;
&lt;br /&gt;
We will need several inter-connected AI applications. &lt;br /&gt;
&lt;br /&gt;
====Ollama installation====&lt;br /&gt;
&lt;br /&gt;
We want to be able to run a variety of LLMs so will setup Ollama with a &lt;br /&gt;
* Container name ollama and a yaml file as follows&lt;br /&gt;
 services:&lt;br /&gt;
   ollama:&lt;br /&gt;
     image: ollama/ollama:latest&lt;br /&gt;
     container_name: ollama&lt;br /&gt;
     volumes:&lt;br /&gt;
       - /mnt/docker_data/ollama:/root/.ollama&lt;br /&gt;
     networks:&lt;br /&gt;
       - ai-network&lt;br /&gt;
     deploy:&lt;br /&gt;
       resources:&lt;br /&gt;
         reservations:&lt;br /&gt;
           devices:&lt;br /&gt;
             - driver: nvidia&lt;br /&gt;
               count: 1&lt;br /&gt;
               capabilities:&lt;br /&gt;
                 - gpu&lt;br /&gt;
     restart: unless-stopped&lt;br /&gt;
 networks:&lt;br /&gt;
   ai-network:&lt;br /&gt;
     external: true&lt;br /&gt;
&lt;br /&gt;
* Note that the device driver is set to nvidia&lt;br /&gt;
* To verify it&#039;s in the GPU&lt;br /&gt;
 docker exec -it ollama nvidia-smi&lt;br /&gt;
&lt;br /&gt;
====Loading a model via SSH ====&lt;br /&gt;
Since Ollama is running as a container, we don&#039;t run ollama run directly on the Quince host. We run it through Docker &lt;br /&gt;
* To download and start chatting with a model immediately:&lt;br /&gt;
 docker exec -it ollama ollama run llama3.1:8b&lt;br /&gt;
* To just download (pull) a model to the disk without starting a chat:&lt;br /&gt;
 docker exec -it ollama ollama pull mistral:7b&lt;br /&gt;
*What happens next&lt;br /&gt;
** Ollama will download the model manifest and layers.&lt;br /&gt;
** Because you mapped /mnt/docker_data/ollama, these models are saved to the SSD-backed 100GB config drive, ensuring they load into the 5060 Ti&#039;s VRAM almost instantly.&lt;br /&gt;
* To check what is currently on your disk, complete with the version and size run: &lt;br /&gt;
 docker exec -it ollama ollama list&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ Expected Models&lt;br /&gt;
|-&lt;br /&gt;
! Model	!! Size !! Why run it?&lt;br /&gt;
|-&lt;br /&gt;
| Llama 3.2 (3B) ||	~2.0 GB	|| Lightning fast. Great for simple summaries and quick tasks.&lt;br /&gt;
|-&lt;br /&gt;
| Mistral (7B) || ~4.1 GB || The &amp;quot;Gold Standard&amp;quot; for general purpose local AI. Very reliable.&lt;br /&gt;
|-&lt;br /&gt;
| Llama 3.1 (8B) || ~4.7 GB || Excellent reasoning; very &amp;quot;human&amp;quot; in its responses.&lt;br /&gt;
|-&lt;br /&gt;
|DeepSeek-Coder (6.7B) || ~4.0 GB || If you want help writing scripts or fixing Nginx configs.&lt;br /&gt;
|-&lt;br /&gt;
|Command R (35B) || ~20 GB || The Stretch Goal. At 4-bit quantization, this might fit or spill slightly into system RAM. It’s incredibly smart for document analysis.&lt;br /&gt;
|-&lt;br /&gt;
|Qwen2.5-Coder || ~4.7 GB || Good for coding in Go&lt;br /&gt;
|-&lt;br /&gt;
|GPT-OSS:20B || ~13 GB ||&lt;br /&gt;
|-&lt;br /&gt;
|gemma3:12b || ~8.1 GB ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When you run the command, Ollama tells you exactly what it&#039;s doing in the terminal.&lt;br /&gt;
* For Mistral: It pulls the 7B version by default so no need to be specific. &lt;br /&gt;
 docker exec -it ollama ollama run mistral &lt;br /&gt;
* For Llama: it pulls the 8B version by default.&lt;br /&gt;
 docker exec -it ollama ollama run llama3.1&lt;br /&gt;
To be 100% specific, you can use &amp;quot;tags&amp;quot; like this:&lt;br /&gt;
 docker exec -it ollama ollama run mistral:7b&lt;br /&gt;
 docker exec -it ollama ollama run llama3.1:8b&lt;br /&gt;
&lt;br /&gt;
* How to verify it&#039;s in the GPU (The &amp;quot;Acid Test&amp;quot;). This is the most important part for the 5060 Ti. While chatting with a model in one SSH window, open a second SSH window and run:&lt;br /&gt;
 docker exec -it ollama nvidia-smi&lt;br /&gt;
Look at the Memory-Usage and the Processes list at the bottom. It should show ollama using ~4.5 GB or ~5.2 GB of VRAM, it is successfully running on the GPU. If it stays at 4MiB / 16311MiB, it’s &amp;quot;hallucinating&amp;quot; on your CPU instead, and we’d need to check the drivers.&lt;br /&gt;
&lt;br /&gt;
===AnythingLLM ===&lt;br /&gt;
&lt;br /&gt;
The objective of AnythingLLM is to take data from personal data stores like a collection of books or other data store and use a LLM from Ollama to extract information as required, for example if the data source is a concerned with Go programming language, the user could have the LLM write a Go application while being safe in the knowledge that no outside influence will have tainted the code. So the main uses can be summed up as:&lt;br /&gt;
* &#039;&#039;&#039;Retrieval-Augmented Generation (RAG):&#039;&#039;&#039; This is the &amp;quot;killer feature.&amp;quot; It allows the user to ask a model (like Mistral) questions about their own files. Instead of the AI guessing, it &amp;quot;reads&amp;quot; the ArchiveBox documents first and provides answers based only on their data.&lt;br /&gt;
* &#039;&#039;&#039;Workspace Isolation:&#039;&#039;&#039; It can use different &amp;quot;Workspaces&amp;quot; (e.g., one for Research, one for Home Server Logs, one for Family History). Each workspace has its own specific set of documents and its own &amp;quot;personality,&amp;quot; so the AI doesn&#039;t get confused between work and hobbies.&lt;br /&gt;
* &#039;&#039;&#039;Multi-User &amp;quot;ChatGPT&amp;quot; Experience:&#039;&#039;&#039; It provides a polished, web-based interface that feels like ChatGPT but is hosted at http://quince.seaoffate.net(only from within the local network). This allows the use of the AI from any device on the local network (or via Raisin) without needing to use the SSH terminal.&lt;br /&gt;
* &#039;&#039;&#039;AI Agent Hub:&#039;&#039;&#039; Beyond just chatting, AnythingLLM can act as an Agent. It can browse the web, scrape new URLs given to it, even summarize entire folders of transcripts from the new Whisper-WebUI setup.&lt;br /&gt;
&lt;br /&gt;
Why? Docker’s internal DNS resolves the name ollama to the correct internal IP automatically because they are on the same network.&lt;br /&gt;
* It should be mentioned that the network isolation provided by both Ollama and Anythingllm residing on the ai-network means AnythingLLM can reach the LLM at http://ollama:11434. This internal traffic never touches the main LAN, keeping the AI conversations extremely fast and private from other devices on the local network.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
The AnythingLLM can be installed with the name &amp;quot;anythingllm&amp;quot; and the yaml file below&lt;br /&gt;
 services:&lt;br /&gt;
   anythingllm:&lt;br /&gt;
     image: mintplexlabs/anythingllm:latest&lt;br /&gt;
     container_name: anythingllm&lt;br /&gt;
     ports:&lt;br /&gt;
       - 3001:3001&lt;br /&gt;
     cap_add:&lt;br /&gt;
       - SYS_ADMIN&lt;br /&gt;
     environment:&lt;br /&gt;
       - STORAGE_DIR=/app/server/storage&lt;br /&gt;
     volumes:&lt;br /&gt;
       - /mnt/docker_data/anythingllm:/app/server/storage&lt;br /&gt;
       - /mnt/docker_data/anythingllm/.env:/app/server/.env&lt;br /&gt;
       # This links the Blackberry NFS mount into AnythingLLM&lt;br /&gt;
       - /mnt/archive_data/archivebox:/app/server/storage/documents/archivebox:ro&lt;br /&gt;
     networks:&lt;br /&gt;
       - ai-network&lt;br /&gt;
     restart: unless-stopped&lt;br /&gt;
 networks:&lt;br /&gt;
   ai-network:&lt;br /&gt;
     external: true&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====🌐The &amp;quot;ai-network&amp;quot; Handshake====&lt;br /&gt;
Since we defined ai-network as an external network that both Ollama and AnythingLLM share, they can talk to each other using their Container Names instead of IP addresses. Inside the AnythingLLM Settings UI: &lt;br /&gt;
* &#039;&#039;&#039;LLM Provider:&#039;&#039;&#039; Select Ollama.&lt;br /&gt;
* &#039;&#039;&#039;Ollama URL:&#039;&#039;&#039; Use http://ollama:11434 (Not localhost and not the IP).&lt;br /&gt;
* Why? Docker’s internal DNS resolves the name ollama to the correct internal IP automatically because they are on the same network.&lt;br /&gt;
&lt;br /&gt;
====📂The ArchiveBox &amp;quot;Read-Only&amp;quot; Link====&lt;br /&gt;
The volume mapping for ArchiveBox is very clever&lt;br /&gt;
 /mnt/archive_data/archivebox:/app/server/storage/documents/archivebox:ro&lt;br /&gt;
&#039;&#039;&#039;We should note:&#039;&#039;&#039;&lt;br /&gt;
* The :ro flag: This is critical. It ensures AnythingLLM can read the archives to &amp;quot;learn&amp;quot; from them, but it can never accidentally delete or modify the ArchiveBox data.&lt;br /&gt;
* Visibility: In the AnythingLLM UI, when we go to &amp;quot;Upload Documents,&amp;quot; we will see a folder named archivebox. We can then move those files into your Workspace to start chatting with our archived websites.&lt;br /&gt;
&lt;br /&gt;
====🛠️Environment &amp;amp; Permissions====&lt;br /&gt;
* &#039;&#039;&#039;The .env file:&#039;&#039;&#039; We are mounting /mnt/docker_data/anythingllm/.env. Before we run docker compose up, we make sure that file actually exists (even if it&#039;s empty) or Docker might create it as a folder by mistake.&lt;br /&gt;
** Quick fix: touch /mnt/docker_data/anythingllm/.env&lt;br /&gt;
* SYS_ADMIN Capability: This is required by AnythingLLM because it uses a technology called Puppeteer to scrape websites. Without this &amp;quot;cap_add,&amp;quot; the document scraper will likely fail.&lt;br /&gt;
&lt;br /&gt;
====📊 Quince GPU Status (Ollama + AnythingLLM)====&lt;br /&gt;
 Ollama Memory: 4900MiB / 16311MiB&lt;br /&gt;
The &amp;quot;Quiet&amp;quot; Documentation: Now that AnythingLLM is joining the party on Quince:&lt;br /&gt;
* VRAM: AnythingLLM itself uses almost zero VRAM. It just sends instructions to Ollama.&lt;br /&gt;
* Concurrency: You can have Jellyfin transcoding a movie, Ollama running Mistral, and AnythingLLM scraping a document all at once on that 5060 Ti.&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=AI_%26_Jellyfin&amp;diff=1506</id>
		<title>AI &amp; Jellyfin</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=AI_%26_Jellyfin&amp;diff=1506"/>
		<updated>2026-04-20T18:51:19Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Docker Applications installed on Quince */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
The objective for Quince is to make it the power house Virtual Machine for the AI so it needs to have the [[Linux Docker And GPU Passthrough | Nvidia 5060TI GPU passthrough ]] completed . At the same time it will also run a media server in the form of Jellyfin so that the GPU can do the transcoding. With the AI being serviced by this host we can use &#039;&#039;&#039;[[Data Archive | Blackberry]]&#039;&#039;&#039; for the Data Harvesting.&lt;br /&gt;
&lt;br /&gt;
== Docker Applications installed on Quince ==&lt;br /&gt;
&lt;br /&gt;
We are going to need to install several applications that will share the GPU. The first will be Dockge so that any new containers can be managed easily. We will also need to install Ollama so that we can run LLMs easily. Then to make use of the data archive we can use AnythingLLM.&lt;br /&gt;
&lt;br /&gt;
==Installation Strategy==&lt;br /&gt;
&lt;br /&gt;
Once the Blackwell GPU passthrough was verified on the Pear host, we transitioned to the Quince VM to set up the containerized environment. This allows us to run high-performance AI (Ollama) and media (Jellyfin) apps while keeping the base OS clean.&lt;br /&gt;
&lt;br /&gt;
===Docker Engine Installation===&lt;br /&gt;
&lt;br /&gt;
We use the official Docker repository to ensure access to v29+, which includes critical patches for Gen 5 PCIe and Blackwell architecture support.&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt install ca-certificates curl gnupg&lt;br /&gt;
Then setup the repository&lt;br /&gt;
 sudo install -m 0755 -d /etc/apt/keyrings&lt;br /&gt;
 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg&lt;br /&gt;
 sudo chmod a+r /etc/apt/keyrings/docker.gpg&lt;br /&gt;
 echo &amp;quot;deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;$VERSION_CODENAME&amp;quot;) stable&amp;quot; | sudo tee /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null&lt;br /&gt;
Next Install Engine &amp;amp; Compose&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;br /&gt;
===NVIDIA Container Toolkit (The &amp;quot;Magic Bridge&amp;quot;)===&lt;br /&gt;
This toolkit enables the libnvidia-container library, which maps the physical GPU device files (/dev/nvidia0, etc.) into the virtualized Docker namespace.&lt;br /&gt;
 curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg&lt;br /&gt;
 curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | sed &#039;s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g&#039; | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt install -y nvidia-container-toolkit&lt;br /&gt;
and last we configure the Nvidia Container tool Kit and restart Docker&lt;br /&gt;
 sudo nvidia-ctk runtime configure --runtime=docker&lt;br /&gt;
 sudo systemctl restart docker&lt;br /&gt;
&lt;br /&gt;
==Docker Applications==&lt;br /&gt;
&lt;br /&gt;
===Dockge Setup===&lt;br /&gt;
Now that docker is installed we can install Dockge. To get Dockge running on Quince, we followed a specific path that keeps it isolated but powerful enough to manage your other stacks (Jellyfin, AnythingLLM, etc.).&lt;br /&gt;
Since Dockge is a &amp;quot;Docker manager that runs inside Docker,&amp;quot; the installation is a bit like a &amp;quot;Inception&amp;quot; move, we create a directory for it, and then use a simple script or a compose.yaml to launch it. &lt;br /&gt;
* Create the Directory Structure On Quince, we created a dedicated space for Dockge and all the future stacks you&#039;ll build. open a terminal and run the following &lt;br /&gt;
 mkdir -p /mnt/docker_data/dockge /mnt/docker_data/stacks&lt;br /&gt;
 cd /mnt/docker_data/dockge&lt;br /&gt;
* Download the Compose File We pulled the official configuration. Dockge needs access to the Docker Socket (/var/run/docker.sock) so it can &amp;quot;reach out&amp;quot; and control the other containers on Quince.&lt;br /&gt;
 curl https://raw.githubusercontent.com/louislam/dockge/master/compose.yaml --output compose.yaml&lt;br /&gt;
* Launch Dockge We started it up in &amp;quot;detached&amp;quot; mode.&lt;br /&gt;
 docker compose up -d&lt;br /&gt;
Now that Dockge is running we have a web interface on Quince:5001 and we can use it to add new services.&lt;br /&gt;
&lt;br /&gt;
===Jellyfin Installation===&lt;br /&gt;
&lt;br /&gt;
To give the media server plenty of storage we have mounted a 3TB data drive at /mnt/jellyfin/ to store all of the media files, we have another drive at /mnt/docker_data to hold all of the configuration data for the containers. We had some difficulty with a left over jellyfin container instalation so we called this container jellyfin-new. The yaml file for &amp;quot;jellyfin-new&amp;quot; is as follows.&lt;br /&gt;
&lt;br /&gt;
 services:&lt;br /&gt;
   jellyfin:&lt;br /&gt;
     image: jellyfin/jellyfin&lt;br /&gt;
     container_name: jellyfin&lt;br /&gt;
     user: 1000:1000&lt;br /&gt;
     # ADD THIS SECTION:&lt;br /&gt;
     runtime: nvidia # Tells Docker to use the NVIDIA Container Toolkit&lt;br /&gt;
     deploy:&lt;br /&gt;
       resources:&lt;br /&gt;
         reservations:&lt;br /&gt;
           devices:&lt;br /&gt;
             - driver: nvidia&lt;br /&gt;
               count: 1&lt;br /&gt;
               capabilities: [gpu, video] # Grants access to NVENC/NVDEC&lt;br /&gt;
     ports:&lt;br /&gt;
       - 8096:8096&lt;br /&gt;
     volumes:&lt;br /&gt;
       - /mnt/docker_data/jellyfin/config:/config&lt;br /&gt;
       - /mnt/docker_data/jellyfin/cache:/cache&lt;br /&gt;
       - /mnt/jellyfin/audiobooks:/data/audiobooks&lt;br /&gt;
       - /mnt/jellyfin/oldfilms:/data/movies&lt;br /&gt;
       - /mnt/jellyfin/oldseries:/data/tvshows&lt;br /&gt;
       - /mnt/jellyfin/dji:/data/dji&lt;br /&gt;
     restart: unless-stopped&lt;br /&gt;
 networks: {}&lt;br /&gt;
&lt;br /&gt;
The web interface for Jellyfin is on port 8096 so http://quince:8096 will bring it up. To setup the local devices either with a webrowser or the Jellyfin Media player the firewall will forward 8096 to the media server.&lt;br /&gt;
* To use the Nvidia Toolkit with jellyfin we set the device driver to nvidia in the yaml file.&lt;br /&gt;
* After clicking &amp;quot;Deploy&amp;quot; in Dockge, we can verified the container could &amp;quot;talk&amp;quot; to the 5060 Ti with the command&lt;br /&gt;
 docker exec -it jellyfin nvidia-smi&lt;br /&gt;
We should have an output with the line something like &lt;br /&gt;
 NVIDIA-SMI 580.126.09             Driver Version: 580.126.09     CUDA Version: 13.0 &lt;br /&gt;
====Post-Install Playback Optimization====&lt;br /&gt;
Inside the Jellyfin Web UI (Dashboard &amp;gt; Playback), we have enabled Nvidia NVENC and checked the following critical Blackwell features:&lt;br /&gt;
* Hardware Decoding: H264, HEVC, AV1, VP9.&lt;br /&gt;
* AV1 Encoding: Allowed (The 5060 Ti is one of the few cards that can do this, significantly saving bandwidth).&lt;br /&gt;
* Tone Mapping: Enabled (Necessary for playing 4K HDR DJI drone footage on SDR screens).&lt;br /&gt;
&lt;br /&gt;
===AI applications ===&lt;br /&gt;
&lt;br /&gt;
We will need several inter-connected AI applications. &lt;br /&gt;
&lt;br /&gt;
====Ollama installation====&lt;br /&gt;
&lt;br /&gt;
We want to be able to run a variety of LLMs so will setup Ollama with a &lt;br /&gt;
* Container name ollama and a yaml file as follows&lt;br /&gt;
 services:&lt;br /&gt;
   ollama:&lt;br /&gt;
     image: ollama/ollama:latest&lt;br /&gt;
     container_name: ollama&lt;br /&gt;
     volumes:&lt;br /&gt;
       - /mnt/docker_data/ollama:/root/.ollama&lt;br /&gt;
     networks:&lt;br /&gt;
       - ai-network&lt;br /&gt;
     deploy:&lt;br /&gt;
       resources:&lt;br /&gt;
         reservations:&lt;br /&gt;
           devices:&lt;br /&gt;
             - driver: nvidia&lt;br /&gt;
               count: 1&lt;br /&gt;
               capabilities:&lt;br /&gt;
                 - gpu&lt;br /&gt;
     restart: unless-stopped&lt;br /&gt;
 networks:&lt;br /&gt;
   ai-network:&lt;br /&gt;
     external: true&lt;br /&gt;
&lt;br /&gt;
* Note that the device driver is set to nvidia&lt;br /&gt;
* To verify it&#039;s in the GPU&lt;br /&gt;
 docker exec -it ollama nvidia-smi&lt;br /&gt;
&lt;br /&gt;
====Loading a model via SSH ====&lt;br /&gt;
Since Ollama is running as a container, we don&#039;t run ollama run directly on the Quince host. We run it through Docker &lt;br /&gt;
* To download and start chatting with a model immediately:&lt;br /&gt;
 docker exec -it ollama ollama run llama3.1:8b&lt;br /&gt;
* To just download (pull) a model to the disk without starting a chat:&lt;br /&gt;
 docker exec -it ollama ollama pull mistral:7b&lt;br /&gt;
*What happens next&lt;br /&gt;
** Ollama will download the model manifest and layers.&lt;br /&gt;
** Because you mapped /mnt/docker_data/ollama, these models are saved to the SSD-backed 100GB config drive, ensuring they load into the 5060 Ti&#039;s VRAM almost instantly.&lt;br /&gt;
* To check what is currently on your disk, complete with the version and size run: &lt;br /&gt;
 docker exec -it ollama ollama list&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|+ Expected Models&lt;br /&gt;
|-&lt;br /&gt;
! Model	!! Size !! Why run it?&lt;br /&gt;
|-&lt;br /&gt;
| Llama 3.2 (3B) ||	~2.0 GB	|| Lightning fast. Great for simple summaries and quick tasks.&lt;br /&gt;
|-&lt;br /&gt;
| Mistral (7B) || ~4.1 GB || The &amp;quot;Gold Standard&amp;quot; for general purpose local AI. Very reliable.&lt;br /&gt;
|-&lt;br /&gt;
| Llama 3.1 (8B) || ~4.7 GB || Excellent reasoning; very &amp;quot;human&amp;quot; in its responses.&lt;br /&gt;
|-&lt;br /&gt;
|DeepSeek-Coder (6.7B) || ~4.0 GB || If you want help writing scripts or fixing Nginx configs.&lt;br /&gt;
|-&lt;br /&gt;
|Command R (35B) || ~20 GB || The Stretch Goal. At 4-bit quantization, this might fit or spill slightly into system RAM. It’s incredibly smart for document analysis.&lt;br /&gt;
|-&lt;br /&gt;
|Qwen2.5-Coder || ~4.7 GB || Good for coding in Go&lt;br /&gt;
|-&lt;br /&gt;
|GPT-OSS:20B || ~13 GB ||&lt;br /&gt;
|-&lt;br /&gt;
|gemma3:12b || ~8.1 GB ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When you run the command, Ollama tells you exactly what it&#039;s doing in the terminal.&lt;br /&gt;
* For Mistral: It pulls the 7B version by default so no need to be specific. &lt;br /&gt;
 docker exec -it ollama ollama run mistral &lt;br /&gt;
* For Llama: it pulls the 8B version by default.&lt;br /&gt;
 docker exec -it ollama ollama run llama3.1&lt;br /&gt;
To be 100% specific, you can use &amp;quot;tags&amp;quot; like this:&lt;br /&gt;
 docker exec -it ollama ollama run mistral:7b&lt;br /&gt;
 docker exec -it ollama ollama run llama3.1:8b&lt;br /&gt;
&lt;br /&gt;
* How to verify it&#039;s in the GPU (The &amp;quot;Acid Test&amp;quot;). This is the most important part for the 5060 Ti. While chatting with a model in one SSH window, open a second SSH window and run:&lt;br /&gt;
 docker exec -it ollama nvidia-smi&lt;br /&gt;
Look at the Memory-Usage and the Processes list at the bottom. It should show ollama using ~4.5 GB or ~5.2 GB of VRAM, it is successfully running on the GPU. If it stays at 4MiB / 16311MiB, it’s &amp;quot;hallucinating&amp;quot; on your CPU instead, and we’d need to check the drivers.&lt;br /&gt;
&lt;br /&gt;
===AnythingLLM ===&lt;br /&gt;
&lt;br /&gt;
The objective of AnythingLLM is to take data from personal data stores like a collection of books or other data store and use a LLM from Ollama to extract information as required, for example if the data source is a concerned with Go programming language, the user could have the LLM write a Go application while being safe in the knowledge that no outside influence will have tainted the code. So the main uses can be summed up as:&lt;br /&gt;
* &#039;&#039;&#039;Retrieval-Augmented Generation (RAG):&#039;&#039;&#039; This is the &amp;quot;killer feature.&amp;quot; It allows the user to ask a model (like Mistral) questions about their own files. Instead of the AI guessing, it &amp;quot;reads&amp;quot; the ArchiveBox documents first and provides answers based only on their data.&lt;br /&gt;
* &#039;&#039;&#039;Workspace Isolation:&#039;&#039;&#039; It can use different &amp;quot;Workspaces&amp;quot; (e.g., one for Research, one for Home Server Logs, one for Family History). Each workspace has its own specific set of documents and its own &amp;quot;personality,&amp;quot; so the AI doesn&#039;t get confused between work and hobbies.&lt;br /&gt;
* &#039;&#039;&#039;Multi-User &amp;quot;ChatGPT&amp;quot; Experience:&#039;&#039;&#039; It provides a polished, web-based interface that feels like ChatGPT but is hosted at http://quince.seaoffate.net(only from within the local network). This allows the use of the AI from any device on the local network (or via Raisin) without needing to use the SSH terminal.&lt;br /&gt;
* &#039;&#039;&#039;AI Agent Hub:&#039;&#039;&#039; Beyond just chatting, AnythingLLM can act as an Agent. It can browse the web, scrape new URLs given to it, even summarize entire folders of transcripts from the new Whisper-WebUI setup.&lt;br /&gt;
&lt;br /&gt;
Why? Docker’s internal DNS resolves the name ollama to the correct internal IP automatically because they are on the same network.&lt;br /&gt;
* It should be mentioned that the network isolation provided by both Ollama and Anythingllm residing on the ai-network means AnythingLLM can reach the LLM at http://ollama:11434. This internal traffic never touches the main LAN, keeping the AI conversations extremely fast and private from other devices on the local network.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
The AnythingLLM can be installed with the name &amp;quot;anythingllm&amp;quot; and the yaml file below&lt;br /&gt;
 services:&lt;br /&gt;
   anythingllm:&lt;br /&gt;
     image: mintplexlabs/anythingllm:latest&lt;br /&gt;
     container_name: anythingllm&lt;br /&gt;
     ports:&lt;br /&gt;
       - 3001:3001&lt;br /&gt;
     cap_add:&lt;br /&gt;
       - SYS_ADMIN&lt;br /&gt;
     environment:&lt;br /&gt;
       - STORAGE_DIR=/app/server/storage&lt;br /&gt;
     volumes:&lt;br /&gt;
       - /mnt/docker_data/anythingllm:/app/server/storage&lt;br /&gt;
       - /mnt/docker_data/anythingllm/.env:/app/server/.env&lt;br /&gt;
       # This links the Blackberry NFS mount into AnythingLLM&lt;br /&gt;
       - /mnt/archive_data/archivebox:/app/server/storage/documents/archivebox:ro&lt;br /&gt;
     networks:&lt;br /&gt;
       - ai-network&lt;br /&gt;
     restart: unless-stopped&lt;br /&gt;
 networks:&lt;br /&gt;
   ai-network:&lt;br /&gt;
     external: true&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====🌐The &amp;quot;ai-network&amp;quot; Handshake====&lt;br /&gt;
Since we defined ai-network as an external network that both Ollama and AnythingLLM share, they can talk to each other using their Container Names instead of IP addresses. Inside the AnythingLLM Settings UI: &lt;br /&gt;
* &#039;&#039;&#039;LLM Provider:&#039;&#039;&#039; Select Ollama.&lt;br /&gt;
* &#039;&#039;&#039;Ollama URL:&#039;&#039;&#039; Use http://ollama:11434 (Not localhost and not the IP).&lt;br /&gt;
* Why? Docker’s internal DNS resolves the name ollama to the correct internal IP automatically because they are on the same network.&lt;br /&gt;
&lt;br /&gt;
====📂The ArchiveBox &amp;quot;Read-Only&amp;quot; Link====&lt;br /&gt;
The volume mapping for ArchiveBox is very clever&lt;br /&gt;
 /mnt/archive_data/archivebox:/app/server/storage/documents/archivebox:ro&lt;br /&gt;
&#039;&#039;&#039;We should note:&#039;&#039;&#039;&lt;br /&gt;
* The :ro flag: This is critical. It ensures AnythingLLM can read the archives to &amp;quot;learn&amp;quot; from them, but it can never accidentally delete or modify the ArchiveBox data.&lt;br /&gt;
* Visibility: In the AnythingLLM UI, when we go to &amp;quot;Upload Documents,&amp;quot; we will see a folder named archivebox. We can then move those files into your Workspace to start chatting with our archived websites.&lt;br /&gt;
&lt;br /&gt;
====🛠️Environment &amp;amp; Permissions====&lt;br /&gt;
* &#039;&#039;&#039;The .env file:&#039;&#039;&#039; We are mounting /mnt/docker_data/anythingllm/.env. Before we run docker compose up, we make sure that file actually exists (even if it&#039;s empty) or Docker might create it as a folder by mistake.&lt;br /&gt;
** Quick fix: touch /mnt/docker_data/anythingllm/.env&lt;br /&gt;
* SYS_ADMIN Capability: This is required by AnythingLLM because it uses a technology called Puppeteer to scrape websites. Without this &amp;quot;cap_add,&amp;quot; the document scraper will likely fail.&lt;br /&gt;
&lt;br /&gt;
====📊 Quince GPU Status (Ollama + AnythingLLM)====&lt;br /&gt;
 Ollama Memory: 4900MiB / 16311MiB&lt;br /&gt;
The &amp;quot;Quiet&amp;quot; Documentation: Now that AnythingLLM is joining the party on Quince:&lt;br /&gt;
* VRAM: AnythingLLM itself uses almost zero VRAM. It just sends instructions to Ollama.&lt;br /&gt;
* Concurrency: You can have Jellyfin transcoding a movie, Ollama running Mistral, and AnythingLLM scraping a document all at once on that 5060 Ti.&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Homelab_Dashboard&amp;diff=1505</id>
		<title>Homelab Dashboard</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Homelab_Dashboard&amp;diff=1505"/>
		<updated>2026-04-20T18:50:03Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We have decided to setup a &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039; dashboard to monitor and administer the entire estate of &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;, &#039;&#039;&#039;[[Proxmox Server | Proxmox]]&#039;&#039;&#039; hosts and all of the services that we have created. initially we will use the dashy dashboard but may well change for something else if dashy proves to be to difficult or in some way unsuitable.&lt;br /&gt;
&lt;br /&gt;
==Dashy Setup==&lt;br /&gt;
&lt;br /&gt;
in the interests of security for this sensitive project we are extending your &amp;quot;Full-Chain TLS&amp;quot; SME standard to Blackberry. This ensures that even if a client bypasses the proxy (Raisin) and hits Blackberry directly on the network, the traffic is still encrypted and presents the valid *.seaoffate.net certificate. It will also mean that within the Pfsense side of the LAN any client will still meet the same secure SSL certificate system provided by Letsencrypt. 🛡️We will mount our existing SSL certificates (synced from Raisin) directly into the Dashy container and configure Dashy to serve HTTPS natively. Details of how the Certs are downloaded and installed can be found &#039;&#039;&#039;[[Letsencrypt SSL Certs |here]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Installation on Blackberry===&lt;br /&gt;
&lt;br /&gt;
🛠️ The &amp;quot;Dockge-Way&amp;quot; Setup, on our Dockge UI on Blackberry, create a new stack called dashy, and use this single, hardened configuration&lt;br /&gt;
 services:&lt;br /&gt;
   dashy:&lt;br /&gt;
     image: lissy93/dashy:latest&lt;br /&gt;
     container_name: dashy&lt;br /&gt;
     restart: unless-stopped&lt;br /&gt;
     ports:&lt;br /&gt;
       - 443:443&lt;br /&gt;
     volumes:&lt;br /&gt;
       # Use the path that we proved works:&lt;br /&gt;
       - /mnt/archive_data/docker_data/stacks/dashy/conf.yml:/app/public/conf.yml&lt;br /&gt;
       # SSL Certificates (Synced from Raisin)&lt;br /&gt;
       - /etc/nginx/ssl/seaoffate.net/fullchain.pem:/etc/ssl/certs/fullchain.pem:ro&lt;br /&gt;
       - /etc/nginx/ssl/seaoffate.net/privkey.pem:/etc/ssl/private/privkey.pem:ro&lt;br /&gt;
     environment:&lt;br /&gt;
       - NODE_ENV=production&lt;br /&gt;
       - DOCKGE_ENABLE_CONSOLE=true&lt;br /&gt;
       - SSL_PUB_KEY_PATH=/etc/ssl/certs/fullchain.pem&lt;br /&gt;
       - SSL_PRIV_KEY_PATH=/etc/ssl/private/privkey.pem&lt;br /&gt;
       - NODE_OPTIONS=--max-old-space-size=2048&lt;br /&gt;
 networks: {}&lt;br /&gt;
&lt;br /&gt;
===Post-Installation Steps ===&lt;br /&gt;
&lt;br /&gt;
====Certificate Synchronization Hook====&lt;br /&gt;
&lt;br /&gt;
Before the container will start correctly in SSL mode, we must have a basic conf.yml in the same directory as our compose.yaml. This file defines our users and our &amp;quot;Fruit Cluster&amp;quot; links. It is better to be sure that the docker app has the correct permissions for the yml, especially if it is in a non standard location.&lt;br /&gt;
 touch sudo nano /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
 sudo chown 1000:1000 /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
 sudo chmod 644 /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note&#039;&#039;&#039; we are using a non standard directory for our stacks, the more common location for the conf.yml is /opt/dockge/stacks/dashy/conf.yml&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To ensure Dashy stays updated when Raisin renews the Wildcard certs, make sure the deploy-wildcard.sh script on Raisin includes the Blackberry sync. It should have the Blackberry host in the servers list and the dashy restart in the if statements something like&lt;br /&gt;
  # Restart Dashy (Blackberry)&lt;br /&gt;
  if [ \$(docker ps -q -f name=dashy) ]; then&lt;br /&gt;
      echo &#039;  Restarting Dashy...&#039;&lt;br /&gt;
      docker restart dashy&lt;br /&gt;
  fi&lt;br /&gt;
&lt;br /&gt;
====Authentication Hardening====&lt;br /&gt;
&lt;br /&gt;
To fulfill the &amp;quot;Secure Application&amp;quot; requirement, we enable Dashy’s internal authentication. Even with a valid SSL cert, no data is visible without a login. Dashy requires a SHA-256 hash for the admin password. Run this on any terminal:&lt;br /&gt;
 echo -n &amp;quot;YourSecretPassword&amp;quot; | sha256sum&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note&#039;&#039;&#039; the quotes are only needed if there is spaces or similar in the password and the quotation marks are not part of the password&#039;&#039;&lt;br /&gt;
Take the resulting string and place it in the auth section of your conf.yml on Blackberry&lt;br /&gt;
 nano /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
A sample conf is as follows ( including the password YourSecretPassword it is assumed that the user will change the hash to some other password):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;appConfig:&lt;br /&gt;
   title: SeaOfFate Command&lt;br /&gt;
   statusCheck: true&lt;br /&gt;
   auth:&lt;br /&gt;
     enable: true&lt;br /&gt;
     enableGuestAccess: false&lt;br /&gt;
     users:&lt;br /&gt;
       - user: nigel&lt;br /&gt;
         hash: &#039;790e294c25e704e042c899bb4dbb696b9daa2ed330d270082599f8591dc62b96&#039;&lt;br /&gt;
         type: admin&lt;br /&gt;
 sections:&lt;br /&gt;
   - name: Infrastructure&lt;br /&gt;
     items:&lt;br /&gt;
       - title: Vaultwarden&lt;br /&gt;
         url: https://vault.seaoffate.net/alive&lt;br /&gt;
         icon: hl-bitwarden&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;💡 Why /alive&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
if you just ping the main URL, Dashy might get a 401 Unauthorized or a redirect, which can sometimes show up as a &amp;quot;Yellow&amp;quot; or &amp;quot;Red&amp;quot; dot even if the service is fine. The /alive path is specifically designed for health checks like this and always returns a simple 200 OK&lt;br /&gt;
&lt;br /&gt;
====Verification====&lt;br /&gt;
&lt;br /&gt;
Once started, you can verify the &amp;quot;Full-Chain TLS&amp;quot; by visiting:&lt;br /&gt;
* Internal(inside Pfsence): https://192.168.100.85 (Should show the valid seaoffate.net certificate from letsencrypt ).&lt;br /&gt;
* Internal(inside Pfsence): https://blackberry  (Assuming the internal nameserver ctns1 has the DNS entry for blackberry set should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* Internal(inside Pfsence): https://dashy.seaoffate.net (Assuming the internal nameserver ctns1 has the DNS entry for dashy set should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* Internal:(outside Pfsence) https://dashy.seaoffate.net (Assuming the DNS rewrite foe seaoffate.net on adguard set and Raisin reverse proxy rule is set, should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* External(though mobile phone Internet): https://dashy.seaoffate.net (Assuming the DNS for dashy is set on Cloudflare&#039;s control panel and dashy is proxied through Raisin it should show the Cloudflare SSL certificate).&lt;br /&gt;
When we have proved that the the dashboard works and that the login screen is displayed first we can move on to adding items to the dashboard.&lt;br /&gt;
&lt;br /&gt;
==Configuring the Dashboard==&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Homelab_Dashboard&amp;diff=1504</id>
		<title>Homelab Dashboard</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Homelab_Dashboard&amp;diff=1504"/>
		<updated>2026-04-20T18:48:49Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We have decided to setup a &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039; dashboard to monitor and administer the entire estate of &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;, &#039;&#039;&#039;[[Proxmox Server| Proxmox]]&#039;&#039;&#039; hosts and all of the services that we have created. initially we will use the dashy dashboard but may well change for something else if dashy proves to be to difficult or in some way unsuitable.&lt;br /&gt;
&lt;br /&gt;
==Dashy Setup==&lt;br /&gt;
&lt;br /&gt;
in the interests of security for this sensitive project we are extending your &amp;quot;Full-Chain TLS&amp;quot; SME standard to Blackberry. This ensures that even if a client bypasses the proxy (Raisin) and hits Blackberry directly on the network, the traffic is still encrypted and presents the valid *.seaoffate.net certificate. It will also mean that within the Pfsense side of the LAN any client will still meet the same secure SSL certificate system provided by Letsencrypt. 🛡️We will mount our existing SSL certificates (synced from Raisin) directly into the Dashy container and configure Dashy to serve HTTPS natively. Details of how the Certs are downloaded and installed can be found &#039;&#039;&#039;[[Letsencrypt SSL Certs |here]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Installation on Blackberry===&lt;br /&gt;
&lt;br /&gt;
🛠️ The &amp;quot;Dockge-Way&amp;quot; Setup, on our Dockge UI on Blackberry, create a new stack called dashy, and use this single, hardened configuration&lt;br /&gt;
 services:&lt;br /&gt;
   dashy:&lt;br /&gt;
     image: lissy93/dashy:latest&lt;br /&gt;
     container_name: dashy&lt;br /&gt;
     restart: unless-stopped&lt;br /&gt;
     ports:&lt;br /&gt;
       - 443:443&lt;br /&gt;
     volumes:&lt;br /&gt;
       # Use the path that we proved works:&lt;br /&gt;
       - /mnt/archive_data/docker_data/stacks/dashy/conf.yml:/app/public/conf.yml&lt;br /&gt;
       # SSL Certificates (Synced from Raisin)&lt;br /&gt;
       - /etc/nginx/ssl/seaoffate.net/fullchain.pem:/etc/ssl/certs/fullchain.pem:ro&lt;br /&gt;
       - /etc/nginx/ssl/seaoffate.net/privkey.pem:/etc/ssl/private/privkey.pem:ro&lt;br /&gt;
     environment:&lt;br /&gt;
       - NODE_ENV=production&lt;br /&gt;
       - DOCKGE_ENABLE_CONSOLE=true&lt;br /&gt;
       - SSL_PUB_KEY_PATH=/etc/ssl/certs/fullchain.pem&lt;br /&gt;
       - SSL_PRIV_KEY_PATH=/etc/ssl/private/privkey.pem&lt;br /&gt;
       - NODE_OPTIONS=--max-old-space-size=2048&lt;br /&gt;
 networks: {}&lt;br /&gt;
&lt;br /&gt;
===Post-Installation Steps ===&lt;br /&gt;
&lt;br /&gt;
====Certificate Synchronization Hook====&lt;br /&gt;
&lt;br /&gt;
Before the container will start correctly in SSL mode, we must have a basic conf.yml in the same directory as our compose.yaml. This file defines our users and our &amp;quot;Fruit Cluster&amp;quot; links. It is better to be sure that the docker app has the correct permissions for the yml, especially if it is in a non standard location.&lt;br /&gt;
 touch sudo nano /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
 sudo chown 1000:1000 /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
 sudo chmod 644 /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note&#039;&#039;&#039; we are using a non standard directory for our stacks, the more common location for the conf.yml is /opt/dockge/stacks/dashy/conf.yml&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To ensure Dashy stays updated when Raisin renews the Wildcard certs, make sure the deploy-wildcard.sh script on Raisin includes the Blackberry sync. It should have the Blackberry host in the servers list and the dashy restart in the if statements something like&lt;br /&gt;
  # Restart Dashy (Blackberry)&lt;br /&gt;
  if [ \$(docker ps -q -f name=dashy) ]; then&lt;br /&gt;
      echo &#039;  Restarting Dashy...&#039;&lt;br /&gt;
      docker restart dashy&lt;br /&gt;
  fi&lt;br /&gt;
&lt;br /&gt;
====Authentication Hardening====&lt;br /&gt;
&lt;br /&gt;
To fulfill the &amp;quot;Secure Application&amp;quot; requirement, we enable Dashy’s internal authentication. Even with a valid SSL cert, no data is visible without a login. Dashy requires a SHA-256 hash for the admin password. Run this on any terminal:&lt;br /&gt;
 echo -n &amp;quot;YourSecretPassword&amp;quot; | sha256sum&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note&#039;&#039;&#039; the quotes are only needed if there is spaces or similar in the password and the quotation marks are not part of the password&#039;&#039;&lt;br /&gt;
Take the resulting string and place it in the auth section of your conf.yml on Blackberry&lt;br /&gt;
 nano /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
A sample conf is as follows ( including the password YourSecretPassword it is assumed that the user will change the hash to some other password):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;appConfig:&lt;br /&gt;
   title: SeaOfFate Command&lt;br /&gt;
   statusCheck: true&lt;br /&gt;
   auth:&lt;br /&gt;
     enable: true&lt;br /&gt;
     enableGuestAccess: false&lt;br /&gt;
     users:&lt;br /&gt;
       - user: nigel&lt;br /&gt;
         hash: &#039;790e294c25e704e042c899bb4dbb696b9daa2ed330d270082599f8591dc62b96&#039;&lt;br /&gt;
         type: admin&lt;br /&gt;
 sections:&lt;br /&gt;
   - name: Infrastructure&lt;br /&gt;
     items:&lt;br /&gt;
       - title: Vaultwarden&lt;br /&gt;
         url: https://vault.seaoffate.net/alive&lt;br /&gt;
         icon: hl-bitwarden&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;💡 Why /alive&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
if you just ping the main URL, Dashy might get a 401 Unauthorized or a redirect, which can sometimes show up as a &amp;quot;Yellow&amp;quot; or &amp;quot;Red&amp;quot; dot even if the service is fine. The /alive path is specifically designed for health checks like this and always returns a simple 200 OK&lt;br /&gt;
&lt;br /&gt;
====Verification====&lt;br /&gt;
&lt;br /&gt;
Once started, you can verify the &amp;quot;Full-Chain TLS&amp;quot; by visiting:&lt;br /&gt;
* Internal(inside Pfsence): https://192.168.100.85 (Should show the valid seaoffate.net certificate from letsencrypt ).&lt;br /&gt;
* Internal(inside Pfsence): https://blackberry  (Assuming the internal nameserver ctns1 has the DNS entry for blackberry set should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* Internal(inside Pfsence): https://dashy.seaoffate.net (Assuming the internal nameserver ctns1 has the DNS entry for dashy set should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* Internal:(outside Pfsence) https://dashy.seaoffate.net (Assuming the DNS rewrite foe seaoffate.net on adguard set and Raisin reverse proxy rule is set, should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* External(though mobile phone Internet): https://dashy.seaoffate.net (Assuming the DNS for dashy is set on Cloudflare&#039;s control panel and dashy is proxied through Raisin it should show the Cloudflare SSL certificate).&lt;br /&gt;
When we have proved that the the dashboard works and that the login screen is displayed first we can move on to adding items to the dashboard.&lt;br /&gt;
&lt;br /&gt;
==Configuring the Dashboard==&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Homelab_Dashboard&amp;diff=1503</id>
		<title>Homelab Dashboard</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Homelab_Dashboard&amp;diff=1503"/>
		<updated>2026-04-20T18:47:32Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We have decided to setup a &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039; dashboard to monitor and administer the entire estate of &#039;&#039;&#039;[[Virtual Machines]]&#039;&#039;&#039;, &#039;&#039;&#039;[[Proxmox Server | Proxmox]]&#039;&#039;&#039; hosts and all of the services that we have created. initially we will use the dashy dashboard but may well change for something else if dashy proves to be to difficult or in some way unsuitable.&lt;br /&gt;
&lt;br /&gt;
==Dashy Setup==&lt;br /&gt;
&lt;br /&gt;
in the interests of security for this sensitive project we are extending your &amp;quot;Full-Chain TLS&amp;quot; SME standard to Blackberry. This ensures that even if a client bypasses the proxy (Raisin) and hits Blackberry directly on the network, the traffic is still encrypted and presents the valid *.seaoffate.net certificate. It will also mean that within the Pfsense side of the LAN any client will still meet the same secure SSL certificate system provided by Letsencrypt. 🛡️We will mount our existing SSL certificates (synced from Raisin) directly into the Dashy container and configure Dashy to serve HTTPS natively. Details of how the Certs are downloaded and installed can be found &#039;&#039;&#039;[[Letsencrypt SSL Certs |here]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Installation on Blackberry===&lt;br /&gt;
&lt;br /&gt;
🛠️ The &amp;quot;Dockge-Way&amp;quot; Setup, on our Dockge UI on Blackberry, create a new stack called dashy, and use this single, hardened configuration&lt;br /&gt;
 services:&lt;br /&gt;
   dashy:&lt;br /&gt;
     image: lissy93/dashy:latest&lt;br /&gt;
     container_name: dashy&lt;br /&gt;
     restart: unless-stopped&lt;br /&gt;
     ports:&lt;br /&gt;
       - 443:443&lt;br /&gt;
     volumes:&lt;br /&gt;
       # Use the path that we proved works:&lt;br /&gt;
       - /mnt/archive_data/docker_data/stacks/dashy/conf.yml:/app/public/conf.yml&lt;br /&gt;
       # SSL Certificates (Synced from Raisin)&lt;br /&gt;
       - /etc/nginx/ssl/seaoffate.net/fullchain.pem:/etc/ssl/certs/fullchain.pem:ro&lt;br /&gt;
       - /etc/nginx/ssl/seaoffate.net/privkey.pem:/etc/ssl/private/privkey.pem:ro&lt;br /&gt;
     environment:&lt;br /&gt;
       - NODE_ENV=production&lt;br /&gt;
       - DOCKGE_ENABLE_CONSOLE=true&lt;br /&gt;
       - SSL_PUB_KEY_PATH=/etc/ssl/certs/fullchain.pem&lt;br /&gt;
       - SSL_PRIV_KEY_PATH=/etc/ssl/private/privkey.pem&lt;br /&gt;
       - NODE_OPTIONS=--max-old-space-size=2048&lt;br /&gt;
 networks: {}&lt;br /&gt;
&lt;br /&gt;
===Post-Installation Steps ===&lt;br /&gt;
&lt;br /&gt;
====Certificate Synchronization Hook====&lt;br /&gt;
&lt;br /&gt;
Before the container will start correctly in SSL mode, we must have a basic conf.yml in the same directory as our compose.yaml. This file defines our users and our &amp;quot;Fruit Cluster&amp;quot; links. It is better to be sure that the docker app has the correct permissions for the yml, especially if it is in a non standard location.&lt;br /&gt;
 touch sudo nano /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
 sudo chown 1000:1000 /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
 sudo chmod 644 /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note&#039;&#039;&#039; we are using a non standard directory for our stacks, the more common location for the conf.yml is /opt/dockge/stacks/dashy/conf.yml&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To ensure Dashy stays updated when Raisin renews the Wildcard certs, make sure the deploy-wildcard.sh script on Raisin includes the Blackberry sync. It should have the Blackberry host in the servers list and the dashy restart in the if statements something like&lt;br /&gt;
  # Restart Dashy (Blackberry)&lt;br /&gt;
  if [ \$(docker ps -q -f name=dashy) ]; then&lt;br /&gt;
      echo &#039;  Restarting Dashy...&#039;&lt;br /&gt;
      docker restart dashy&lt;br /&gt;
  fi&lt;br /&gt;
&lt;br /&gt;
====Authentication Hardening====&lt;br /&gt;
&lt;br /&gt;
To fulfill the &amp;quot;Secure Application&amp;quot; requirement, we enable Dashy’s internal authentication. Even with a valid SSL cert, no data is visible without a login. Dashy requires a SHA-256 hash for the admin password. Run this on any terminal:&lt;br /&gt;
 echo -n &amp;quot;YourSecretPassword&amp;quot; | sha256sum&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note&#039;&#039;&#039; the quotes are only needed if there is spaces or similar in the password and the quotation marks are not part of the password&#039;&#039;&lt;br /&gt;
Take the resulting string and place it in the auth section of your conf.yml on Blackberry&lt;br /&gt;
 nano /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
A sample conf is as follows ( including the password YourSecretPassword it is assumed that the user will change the hash to some other password):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;appConfig:&lt;br /&gt;
   title: SeaOfFate Command&lt;br /&gt;
   statusCheck: true&lt;br /&gt;
   auth:&lt;br /&gt;
     enable: true&lt;br /&gt;
     enableGuestAccess: false&lt;br /&gt;
     users:&lt;br /&gt;
       - user: nigel&lt;br /&gt;
         hash: &#039;790e294c25e704e042c899bb4dbb696b9daa2ed330d270082599f8591dc62b96&#039;&lt;br /&gt;
         type: admin&lt;br /&gt;
 sections:&lt;br /&gt;
   - name: Infrastructure&lt;br /&gt;
     items:&lt;br /&gt;
       - title: Vaultwarden&lt;br /&gt;
         url: https://vault.seaoffate.net/alive&lt;br /&gt;
         icon: hl-bitwarden&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;💡 Why /alive&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
if you just ping the main URL, Dashy might get a 401 Unauthorized or a redirect, which can sometimes show up as a &amp;quot;Yellow&amp;quot; or &amp;quot;Red&amp;quot; dot even if the service is fine. The /alive path is specifically designed for health checks like this and always returns a simple 200 OK&lt;br /&gt;
&lt;br /&gt;
====Verification====&lt;br /&gt;
&lt;br /&gt;
Once started, you can verify the &amp;quot;Full-Chain TLS&amp;quot; by visiting:&lt;br /&gt;
* Internal(inside Pfsence): https://192.168.100.85 (Should show the valid seaoffate.net certificate from letsencrypt ).&lt;br /&gt;
* Internal(inside Pfsence): https://blackberry  (Assuming the internal nameserver ctns1 has the DNS entry for blackberry set should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* Internal(inside Pfsence): https://dashy.seaoffate.net (Assuming the internal nameserver ctns1 has the DNS entry for dashy set should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* Internal:(outside Pfsence) https://dashy.seaoffate.net (Assuming the DNS rewrite foe seaoffate.net on adguard set and Raisin reverse proxy rule is set, should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* External(though mobile phone Internet): https://dashy.seaoffate.net (Assuming the DNS for dashy is set on Cloudflare&#039;s control panel and dashy is proxied through Raisin it should show the Cloudflare SSL certificate).&lt;br /&gt;
When we have proved that the the dashboard works and that the login screen is displayed first we can move on to adding items to the dashboard.&lt;br /&gt;
&lt;br /&gt;
==Configuring the Dashboard==&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Homelab_Dashboard&amp;diff=1502</id>
		<title>Homelab Dashboard</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Homelab_Dashboard&amp;diff=1502"/>
		<updated>2026-04-20T18:47:22Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We have decided to setup a &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039; dashboard to monitor and administer the entire estate of &#039;&#039;&#039;[[Virtual machines]]&#039;&#039;&#039;, &#039;&#039;&#039;[[Proxmox Server | Proxmox]]&#039;&#039;&#039; hosts and all of the services that we have created. initially we will use the dashy dashboard but may well change for something else if dashy proves to be to difficult or in some way unsuitable.&lt;br /&gt;
&lt;br /&gt;
==Dashy Setup==&lt;br /&gt;
&lt;br /&gt;
in the interests of security for this sensitive project we are extending your &amp;quot;Full-Chain TLS&amp;quot; SME standard to Blackberry. This ensures that even if a client bypasses the proxy (Raisin) and hits Blackberry directly on the network, the traffic is still encrypted and presents the valid *.seaoffate.net certificate. It will also mean that within the Pfsense side of the LAN any client will still meet the same secure SSL certificate system provided by Letsencrypt. 🛡️We will mount our existing SSL certificates (synced from Raisin) directly into the Dashy container and configure Dashy to serve HTTPS natively. Details of how the Certs are downloaded and installed can be found &#039;&#039;&#039;[[Letsencrypt SSL Certs |here]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Installation on Blackberry===&lt;br /&gt;
&lt;br /&gt;
🛠️ The &amp;quot;Dockge-Way&amp;quot; Setup, on our Dockge UI on Blackberry, create a new stack called dashy, and use this single, hardened configuration&lt;br /&gt;
 services:&lt;br /&gt;
   dashy:&lt;br /&gt;
     image: lissy93/dashy:latest&lt;br /&gt;
     container_name: dashy&lt;br /&gt;
     restart: unless-stopped&lt;br /&gt;
     ports:&lt;br /&gt;
       - 443:443&lt;br /&gt;
     volumes:&lt;br /&gt;
       # Use the path that we proved works:&lt;br /&gt;
       - /mnt/archive_data/docker_data/stacks/dashy/conf.yml:/app/public/conf.yml&lt;br /&gt;
       # SSL Certificates (Synced from Raisin)&lt;br /&gt;
       - /etc/nginx/ssl/seaoffate.net/fullchain.pem:/etc/ssl/certs/fullchain.pem:ro&lt;br /&gt;
       - /etc/nginx/ssl/seaoffate.net/privkey.pem:/etc/ssl/private/privkey.pem:ro&lt;br /&gt;
     environment:&lt;br /&gt;
       - NODE_ENV=production&lt;br /&gt;
       - DOCKGE_ENABLE_CONSOLE=true&lt;br /&gt;
       - SSL_PUB_KEY_PATH=/etc/ssl/certs/fullchain.pem&lt;br /&gt;
       - SSL_PRIV_KEY_PATH=/etc/ssl/private/privkey.pem&lt;br /&gt;
       - NODE_OPTIONS=--max-old-space-size=2048&lt;br /&gt;
 networks: {}&lt;br /&gt;
&lt;br /&gt;
===Post-Installation Steps ===&lt;br /&gt;
&lt;br /&gt;
====Certificate Synchronization Hook====&lt;br /&gt;
&lt;br /&gt;
Before the container will start correctly in SSL mode, we must have a basic conf.yml in the same directory as our compose.yaml. This file defines our users and our &amp;quot;Fruit Cluster&amp;quot; links. It is better to be sure that the docker app has the correct permissions for the yml, especially if it is in a non standard location.&lt;br /&gt;
 touch sudo nano /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
 sudo chown 1000:1000 /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
 sudo chmod 644 /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note&#039;&#039;&#039; we are using a non standard directory for our stacks, the more common location for the conf.yml is /opt/dockge/stacks/dashy/conf.yml&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To ensure Dashy stays updated when Raisin renews the Wildcard certs, make sure the deploy-wildcard.sh script on Raisin includes the Blackberry sync. It should have the Blackberry host in the servers list and the dashy restart in the if statements something like&lt;br /&gt;
  # Restart Dashy (Blackberry)&lt;br /&gt;
  if [ \$(docker ps -q -f name=dashy) ]; then&lt;br /&gt;
      echo &#039;  Restarting Dashy...&#039;&lt;br /&gt;
      docker restart dashy&lt;br /&gt;
  fi&lt;br /&gt;
&lt;br /&gt;
====Authentication Hardening====&lt;br /&gt;
&lt;br /&gt;
To fulfill the &amp;quot;Secure Application&amp;quot; requirement, we enable Dashy’s internal authentication. Even with a valid SSL cert, no data is visible without a login. Dashy requires a SHA-256 hash for the admin password. Run this on any terminal:&lt;br /&gt;
 echo -n &amp;quot;YourSecretPassword&amp;quot; | sha256sum&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note&#039;&#039;&#039; the quotes are only needed if there is spaces or similar in the password and the quotation marks are not part of the password&#039;&#039;&lt;br /&gt;
Take the resulting string and place it in the auth section of your conf.yml on Blackberry&lt;br /&gt;
 nano /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
A sample conf is as follows ( including the password YourSecretPassword it is assumed that the user will change the hash to some other password):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;appConfig:&lt;br /&gt;
   title: SeaOfFate Command&lt;br /&gt;
   statusCheck: true&lt;br /&gt;
   auth:&lt;br /&gt;
     enable: true&lt;br /&gt;
     enableGuestAccess: false&lt;br /&gt;
     users:&lt;br /&gt;
       - user: nigel&lt;br /&gt;
         hash: &#039;790e294c25e704e042c899bb4dbb696b9daa2ed330d270082599f8591dc62b96&#039;&lt;br /&gt;
         type: admin&lt;br /&gt;
 sections:&lt;br /&gt;
   - name: Infrastructure&lt;br /&gt;
     items:&lt;br /&gt;
       - title: Vaultwarden&lt;br /&gt;
         url: https://vault.seaoffate.net/alive&lt;br /&gt;
         icon: hl-bitwarden&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;💡 Why /alive&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
if you just ping the main URL, Dashy might get a 401 Unauthorized or a redirect, which can sometimes show up as a &amp;quot;Yellow&amp;quot; or &amp;quot;Red&amp;quot; dot even if the service is fine. The /alive path is specifically designed for health checks like this and always returns a simple 200 OK&lt;br /&gt;
&lt;br /&gt;
====Verification====&lt;br /&gt;
&lt;br /&gt;
Once started, you can verify the &amp;quot;Full-Chain TLS&amp;quot; by visiting:&lt;br /&gt;
* Internal(inside Pfsence): https://192.168.100.85 (Should show the valid seaoffate.net certificate from letsencrypt ).&lt;br /&gt;
* Internal(inside Pfsence): https://blackberry  (Assuming the internal nameserver ctns1 has the DNS entry for blackberry set should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* Internal(inside Pfsence): https://dashy.seaoffate.net (Assuming the internal nameserver ctns1 has the DNS entry for dashy set should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* Internal:(outside Pfsence) https://dashy.seaoffate.net (Assuming the DNS rewrite foe seaoffate.net on adguard set and Raisin reverse proxy rule is set, should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* External(though mobile phone Internet): https://dashy.seaoffate.net (Assuming the DNS for dashy is set on Cloudflare&#039;s control panel and dashy is proxied through Raisin it should show the Cloudflare SSL certificate).&lt;br /&gt;
When we have proved that the the dashboard works and that the login screen is displayed first we can move on to adding items to the dashboard.&lt;br /&gt;
&lt;br /&gt;
==Configuring the Dashboard==&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Homelab_Dashboard&amp;diff=1501</id>
		<title>Homelab Dashboard</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Homelab_Dashboard&amp;diff=1501"/>
		<updated>2026-04-20T18:46:55Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We have decided to setup a &#039;&#039;&#039;[[Home Lab]]&#039;&#039;&#039; dashboard to monitor and administer the entire estate of Virtual machines, &#039;&#039;&#039;[[Proxmox Server | Proxmox]]&#039;&#039;&#039; hosts and all of the services that we have created. initially we will use the dashy dashboard but may well change for something else if dashy proves to be to difficult or in some way unsuitable.&lt;br /&gt;
&lt;br /&gt;
==Dashy Setup==&lt;br /&gt;
&lt;br /&gt;
in the interests of security for this sensitive project we are extending your &amp;quot;Full-Chain TLS&amp;quot; SME standard to Blackberry. This ensures that even if a client bypasses the proxy (Raisin) and hits Blackberry directly on the network, the traffic is still encrypted and presents the valid *.seaoffate.net certificate. It will also mean that within the Pfsense side of the LAN any client will still meet the same secure SSL certificate system provided by Letsencrypt. 🛡️We will mount our existing SSL certificates (synced from Raisin) directly into the Dashy container and configure Dashy to serve HTTPS natively. Details of how the Certs are downloaded and installed can be found &#039;&#039;&#039;[[Letsencrypt SSL Certs |here]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Installation on Blackberry===&lt;br /&gt;
&lt;br /&gt;
🛠️ The &amp;quot;Dockge-Way&amp;quot; Setup, on our Dockge UI on Blackberry, create a new stack called dashy, and use this single, hardened configuration&lt;br /&gt;
 services:&lt;br /&gt;
   dashy:&lt;br /&gt;
     image: lissy93/dashy:latest&lt;br /&gt;
     container_name: dashy&lt;br /&gt;
     restart: unless-stopped&lt;br /&gt;
     ports:&lt;br /&gt;
       - 443:443&lt;br /&gt;
     volumes:&lt;br /&gt;
       # Use the path that we proved works:&lt;br /&gt;
       - /mnt/archive_data/docker_data/stacks/dashy/conf.yml:/app/public/conf.yml&lt;br /&gt;
       # SSL Certificates (Synced from Raisin)&lt;br /&gt;
       - /etc/nginx/ssl/seaoffate.net/fullchain.pem:/etc/ssl/certs/fullchain.pem:ro&lt;br /&gt;
       - /etc/nginx/ssl/seaoffate.net/privkey.pem:/etc/ssl/private/privkey.pem:ro&lt;br /&gt;
     environment:&lt;br /&gt;
       - NODE_ENV=production&lt;br /&gt;
       - DOCKGE_ENABLE_CONSOLE=true&lt;br /&gt;
       - SSL_PUB_KEY_PATH=/etc/ssl/certs/fullchain.pem&lt;br /&gt;
       - SSL_PRIV_KEY_PATH=/etc/ssl/private/privkey.pem&lt;br /&gt;
       - NODE_OPTIONS=--max-old-space-size=2048&lt;br /&gt;
 networks: {}&lt;br /&gt;
&lt;br /&gt;
===Post-Installation Steps ===&lt;br /&gt;
&lt;br /&gt;
====Certificate Synchronization Hook====&lt;br /&gt;
&lt;br /&gt;
Before the container will start correctly in SSL mode, we must have a basic conf.yml in the same directory as our compose.yaml. This file defines our users and our &amp;quot;Fruit Cluster&amp;quot; links. It is better to be sure that the docker app has the correct permissions for the yml, especially if it is in a non standard location.&lt;br /&gt;
 touch sudo nano /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
 sudo chown 1000:1000 /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
 sudo chmod 644 /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note&#039;&#039;&#039; we are using a non standard directory for our stacks, the more common location for the conf.yml is /opt/dockge/stacks/dashy/conf.yml&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To ensure Dashy stays updated when Raisin renews the Wildcard certs, make sure the deploy-wildcard.sh script on Raisin includes the Blackberry sync. It should have the Blackberry host in the servers list and the dashy restart in the if statements something like&lt;br /&gt;
  # Restart Dashy (Blackberry)&lt;br /&gt;
  if [ \$(docker ps -q -f name=dashy) ]; then&lt;br /&gt;
      echo &#039;  Restarting Dashy...&#039;&lt;br /&gt;
      docker restart dashy&lt;br /&gt;
  fi&lt;br /&gt;
&lt;br /&gt;
====Authentication Hardening====&lt;br /&gt;
&lt;br /&gt;
To fulfill the &amp;quot;Secure Application&amp;quot; requirement, we enable Dashy’s internal authentication. Even with a valid SSL cert, no data is visible without a login. Dashy requires a SHA-256 hash for the admin password. Run this on any terminal:&lt;br /&gt;
 echo -n &amp;quot;YourSecretPassword&amp;quot; | sha256sum&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note&#039;&#039;&#039; the quotes are only needed if there is spaces or similar in the password and the quotation marks are not part of the password&#039;&#039;&lt;br /&gt;
Take the resulting string and place it in the auth section of your conf.yml on Blackberry&lt;br /&gt;
 nano /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
A sample conf is as follows ( including the password YourSecretPassword it is assumed that the user will change the hash to some other password):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;appConfig:&lt;br /&gt;
   title: SeaOfFate Command&lt;br /&gt;
   statusCheck: true&lt;br /&gt;
   auth:&lt;br /&gt;
     enable: true&lt;br /&gt;
     enableGuestAccess: false&lt;br /&gt;
     users:&lt;br /&gt;
       - user: nigel&lt;br /&gt;
         hash: &#039;790e294c25e704e042c899bb4dbb696b9daa2ed330d270082599f8591dc62b96&#039;&lt;br /&gt;
         type: admin&lt;br /&gt;
 sections:&lt;br /&gt;
   - name: Infrastructure&lt;br /&gt;
     items:&lt;br /&gt;
       - title: Vaultwarden&lt;br /&gt;
         url: https://vault.seaoffate.net/alive&lt;br /&gt;
         icon: hl-bitwarden&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;💡 Why /alive&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
if you just ping the main URL, Dashy might get a 401 Unauthorized or a redirect, which can sometimes show up as a &amp;quot;Yellow&amp;quot; or &amp;quot;Red&amp;quot; dot even if the service is fine. The /alive path is specifically designed for health checks like this and always returns a simple 200 OK&lt;br /&gt;
&lt;br /&gt;
====Verification====&lt;br /&gt;
&lt;br /&gt;
Once started, you can verify the &amp;quot;Full-Chain TLS&amp;quot; by visiting:&lt;br /&gt;
* Internal(inside Pfsence): https://192.168.100.85 (Should show the valid seaoffate.net certificate from letsencrypt ).&lt;br /&gt;
* Internal(inside Pfsence): https://blackberry  (Assuming the internal nameserver ctns1 has the DNS entry for blackberry set should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* Internal(inside Pfsence): https://dashy.seaoffate.net (Assuming the internal nameserver ctns1 has the DNS entry for dashy set should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* Internal:(outside Pfsence) https://dashy.seaoffate.net (Assuming the DNS rewrite foe seaoffate.net on adguard set and Raisin reverse proxy rule is set, should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* External(though mobile phone Internet): https://dashy.seaoffate.net (Assuming the DNS for dashy is set on Cloudflare&#039;s control panel and dashy is proxied through Raisin it should show the Cloudflare SSL certificate).&lt;br /&gt;
When we have proved that the the dashboard works and that the login screen is displayed first we can move on to adding items to the dashboard.&lt;br /&gt;
&lt;br /&gt;
==Configuring the Dashboard==&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Homelab_Dashboard&amp;diff=1500</id>
		<title>Homelab Dashboard</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Homelab_Dashboard&amp;diff=1500"/>
		<updated>2026-04-20T18:46:44Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We have decided to setup a &#039;&#039;&#039;[[Home Lab]]&#039;&#039; dashboard to monitor and administer the entire estate of Virtual machines, &#039;&#039;&#039;[[Proxmox Server | Proxmox]]&#039;&#039;&#039; hosts and all of the services that we have created. initially we will use the dashy dashboard but may well change for something else if dashy proves to be to difficult or in some way unsuitable.&lt;br /&gt;
&lt;br /&gt;
==Dashy Setup==&lt;br /&gt;
&lt;br /&gt;
in the interests of security for this sensitive project we are extending your &amp;quot;Full-Chain TLS&amp;quot; SME standard to Blackberry. This ensures that even if a client bypasses the proxy (Raisin) and hits Blackberry directly on the network, the traffic is still encrypted and presents the valid *.seaoffate.net certificate. It will also mean that within the Pfsense side of the LAN any client will still meet the same secure SSL certificate system provided by Letsencrypt. 🛡️We will mount our existing SSL certificates (synced from Raisin) directly into the Dashy container and configure Dashy to serve HTTPS natively. Details of how the Certs are downloaded and installed can be found &#039;&#039;&#039;[[Letsencrypt SSL Certs |here]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Installation on Blackberry===&lt;br /&gt;
&lt;br /&gt;
🛠️ The &amp;quot;Dockge-Way&amp;quot; Setup, on our Dockge UI on Blackberry, create a new stack called dashy, and use this single, hardened configuration&lt;br /&gt;
 services:&lt;br /&gt;
   dashy:&lt;br /&gt;
     image: lissy93/dashy:latest&lt;br /&gt;
     container_name: dashy&lt;br /&gt;
     restart: unless-stopped&lt;br /&gt;
     ports:&lt;br /&gt;
       - 443:443&lt;br /&gt;
     volumes:&lt;br /&gt;
       # Use the path that we proved works:&lt;br /&gt;
       - /mnt/archive_data/docker_data/stacks/dashy/conf.yml:/app/public/conf.yml&lt;br /&gt;
       # SSL Certificates (Synced from Raisin)&lt;br /&gt;
       - /etc/nginx/ssl/seaoffate.net/fullchain.pem:/etc/ssl/certs/fullchain.pem:ro&lt;br /&gt;
       - /etc/nginx/ssl/seaoffate.net/privkey.pem:/etc/ssl/private/privkey.pem:ro&lt;br /&gt;
     environment:&lt;br /&gt;
       - NODE_ENV=production&lt;br /&gt;
       - DOCKGE_ENABLE_CONSOLE=true&lt;br /&gt;
       - SSL_PUB_KEY_PATH=/etc/ssl/certs/fullchain.pem&lt;br /&gt;
       - SSL_PRIV_KEY_PATH=/etc/ssl/private/privkey.pem&lt;br /&gt;
       - NODE_OPTIONS=--max-old-space-size=2048&lt;br /&gt;
 networks: {}&lt;br /&gt;
&lt;br /&gt;
===Post-Installation Steps ===&lt;br /&gt;
&lt;br /&gt;
====Certificate Synchronization Hook====&lt;br /&gt;
&lt;br /&gt;
Before the container will start correctly in SSL mode, we must have a basic conf.yml in the same directory as our compose.yaml. This file defines our users and our &amp;quot;Fruit Cluster&amp;quot; links. It is better to be sure that the docker app has the correct permissions for the yml, especially if it is in a non standard location.&lt;br /&gt;
 touch sudo nano /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
 sudo chown 1000:1000 /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
 sudo chmod 644 /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note&#039;&#039;&#039; we are using a non standard directory for our stacks, the more common location for the conf.yml is /opt/dockge/stacks/dashy/conf.yml&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To ensure Dashy stays updated when Raisin renews the Wildcard certs, make sure the deploy-wildcard.sh script on Raisin includes the Blackberry sync. It should have the Blackberry host in the servers list and the dashy restart in the if statements something like&lt;br /&gt;
  # Restart Dashy (Blackberry)&lt;br /&gt;
  if [ \$(docker ps -q -f name=dashy) ]; then&lt;br /&gt;
      echo &#039;  Restarting Dashy...&#039;&lt;br /&gt;
      docker restart dashy&lt;br /&gt;
  fi&lt;br /&gt;
&lt;br /&gt;
====Authentication Hardening====&lt;br /&gt;
&lt;br /&gt;
To fulfill the &amp;quot;Secure Application&amp;quot; requirement, we enable Dashy’s internal authentication. Even with a valid SSL cert, no data is visible without a login. Dashy requires a SHA-256 hash for the admin password. Run this on any terminal:&lt;br /&gt;
 echo -n &amp;quot;YourSecretPassword&amp;quot; | sha256sum&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note&#039;&#039;&#039; the quotes are only needed if there is spaces or similar in the password and the quotation marks are not part of the password&#039;&#039;&lt;br /&gt;
Take the resulting string and place it in the auth section of your conf.yml on Blackberry&lt;br /&gt;
 nano /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
A sample conf is as follows ( including the password YourSecretPassword it is assumed that the user will change the hash to some other password):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;appConfig:&lt;br /&gt;
   title: SeaOfFate Command&lt;br /&gt;
   statusCheck: true&lt;br /&gt;
   auth:&lt;br /&gt;
     enable: true&lt;br /&gt;
     enableGuestAccess: false&lt;br /&gt;
     users:&lt;br /&gt;
       - user: nigel&lt;br /&gt;
         hash: &#039;790e294c25e704e042c899bb4dbb696b9daa2ed330d270082599f8591dc62b96&#039;&lt;br /&gt;
         type: admin&lt;br /&gt;
 sections:&lt;br /&gt;
   - name: Infrastructure&lt;br /&gt;
     items:&lt;br /&gt;
       - title: Vaultwarden&lt;br /&gt;
         url: https://vault.seaoffate.net/alive&lt;br /&gt;
         icon: hl-bitwarden&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;💡 Why /alive&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
if you just ping the main URL, Dashy might get a 401 Unauthorized or a redirect, which can sometimes show up as a &amp;quot;Yellow&amp;quot; or &amp;quot;Red&amp;quot; dot even if the service is fine. The /alive path is specifically designed for health checks like this and always returns a simple 200 OK&lt;br /&gt;
&lt;br /&gt;
====Verification====&lt;br /&gt;
&lt;br /&gt;
Once started, you can verify the &amp;quot;Full-Chain TLS&amp;quot; by visiting:&lt;br /&gt;
* Internal(inside Pfsence): https://192.168.100.85 (Should show the valid seaoffate.net certificate from letsencrypt ).&lt;br /&gt;
* Internal(inside Pfsence): https://blackberry  (Assuming the internal nameserver ctns1 has the DNS entry for blackberry set should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* Internal(inside Pfsence): https://dashy.seaoffate.net (Assuming the internal nameserver ctns1 has the DNS entry for dashy set should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* Internal:(outside Pfsence) https://dashy.seaoffate.net (Assuming the DNS rewrite foe seaoffate.net on adguard set and Raisin reverse proxy rule is set, should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* External(though mobile phone Internet): https://dashy.seaoffate.net (Assuming the DNS for dashy is set on Cloudflare&#039;s control panel and dashy is proxied through Raisin it should show the Cloudflare SSL certificate).&lt;br /&gt;
When we have proved that the the dashboard works and that the login screen is displayed first we can move on to adding items to the dashboard.&lt;br /&gt;
&lt;br /&gt;
==Configuring the Dashboard==&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Homelab_Dashboard&amp;diff=1499</id>
		<title>Homelab Dashboard</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Homelab_Dashboard&amp;diff=1499"/>
		<updated>2026-04-20T18:46:12Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We have decided to setup a [[Home Lab]] dashboard to monitor and administer the entire estate of Virtual machines, [[Proxmox Server | Proxmox]]hosts and all of the services that we have created. initially we will use the dashy dashboard but may well change for something else if dashy proves to be to difficult or in some way unsuitable.&lt;br /&gt;
&lt;br /&gt;
==Dashy Setup==&lt;br /&gt;
&lt;br /&gt;
in the interests of security for this sensitive project we are extending your &amp;quot;Full-Chain TLS&amp;quot; SME standard to Blackberry. This ensures that even if a client bypasses the proxy (Raisin) and hits Blackberry directly on the network, the traffic is still encrypted and presents the valid *.seaoffate.net certificate. It will also mean that within the Pfsense side of the LAN any client will still meet the same secure SSL certificate system provided by Letsencrypt. 🛡️We will mount our existing SSL certificates (synced from Raisin) directly into the Dashy container and configure Dashy to serve HTTPS natively. Details of how the Certs are downloaded and installed can be found &#039;&#039;&#039;[[Letsencrypt SSL Certs |here]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Installation on Blackberry===&lt;br /&gt;
&lt;br /&gt;
🛠️ The &amp;quot;Dockge-Way&amp;quot; Setup, on our Dockge UI on Blackberry, create a new stack called dashy, and use this single, hardened configuration&lt;br /&gt;
 services:&lt;br /&gt;
   dashy:&lt;br /&gt;
     image: lissy93/dashy:latest&lt;br /&gt;
     container_name: dashy&lt;br /&gt;
     restart: unless-stopped&lt;br /&gt;
     ports:&lt;br /&gt;
       - 443:443&lt;br /&gt;
     volumes:&lt;br /&gt;
       # Use the path that we proved works:&lt;br /&gt;
       - /mnt/archive_data/docker_data/stacks/dashy/conf.yml:/app/public/conf.yml&lt;br /&gt;
       # SSL Certificates (Synced from Raisin)&lt;br /&gt;
       - /etc/nginx/ssl/seaoffate.net/fullchain.pem:/etc/ssl/certs/fullchain.pem:ro&lt;br /&gt;
       - /etc/nginx/ssl/seaoffate.net/privkey.pem:/etc/ssl/private/privkey.pem:ro&lt;br /&gt;
     environment:&lt;br /&gt;
       - NODE_ENV=production&lt;br /&gt;
       - DOCKGE_ENABLE_CONSOLE=true&lt;br /&gt;
       - SSL_PUB_KEY_PATH=/etc/ssl/certs/fullchain.pem&lt;br /&gt;
       - SSL_PRIV_KEY_PATH=/etc/ssl/private/privkey.pem&lt;br /&gt;
       - NODE_OPTIONS=--max-old-space-size=2048&lt;br /&gt;
 networks: {}&lt;br /&gt;
&lt;br /&gt;
===Post-Installation Steps ===&lt;br /&gt;
&lt;br /&gt;
====Certificate Synchronization Hook====&lt;br /&gt;
&lt;br /&gt;
Before the container will start correctly in SSL mode, we must have a basic conf.yml in the same directory as our compose.yaml. This file defines our users and our &amp;quot;Fruit Cluster&amp;quot; links. It is better to be sure that the docker app has the correct permissions for the yml, especially if it is in a non standard location.&lt;br /&gt;
 touch sudo nano /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
 sudo chown 1000:1000 /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
 sudo chmod 644 /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note&#039;&#039;&#039; we are using a non standard directory for our stacks, the more common location for the conf.yml is /opt/dockge/stacks/dashy/conf.yml&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To ensure Dashy stays updated when Raisin renews the Wildcard certs, make sure the deploy-wildcard.sh script on Raisin includes the Blackberry sync. It should have the Blackberry host in the servers list and the dashy restart in the if statements something like&lt;br /&gt;
  # Restart Dashy (Blackberry)&lt;br /&gt;
  if [ \$(docker ps -q -f name=dashy) ]; then&lt;br /&gt;
      echo &#039;  Restarting Dashy...&#039;&lt;br /&gt;
      docker restart dashy&lt;br /&gt;
  fi&lt;br /&gt;
&lt;br /&gt;
====Authentication Hardening====&lt;br /&gt;
&lt;br /&gt;
To fulfill the &amp;quot;Secure Application&amp;quot; requirement, we enable Dashy’s internal authentication. Even with a valid SSL cert, no data is visible without a login. Dashy requires a SHA-256 hash for the admin password. Run this on any terminal:&lt;br /&gt;
 echo -n &amp;quot;YourSecretPassword&amp;quot; | sha256sum&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note&#039;&#039;&#039; the quotes are only needed if there is spaces or similar in the password and the quotation marks are not part of the password&#039;&#039;&lt;br /&gt;
Take the resulting string and place it in the auth section of your conf.yml on Blackberry&lt;br /&gt;
 nano /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
A sample conf is as follows ( including the password YourSecretPassword it is assumed that the user will change the hash to some other password):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;appConfig:&lt;br /&gt;
   title: SeaOfFate Command&lt;br /&gt;
   statusCheck: true&lt;br /&gt;
   auth:&lt;br /&gt;
     enable: true&lt;br /&gt;
     enableGuestAccess: false&lt;br /&gt;
     users:&lt;br /&gt;
       - user: nigel&lt;br /&gt;
         hash: &#039;790e294c25e704e042c899bb4dbb696b9daa2ed330d270082599f8591dc62b96&#039;&lt;br /&gt;
         type: admin&lt;br /&gt;
 sections:&lt;br /&gt;
   - name: Infrastructure&lt;br /&gt;
     items:&lt;br /&gt;
       - title: Vaultwarden&lt;br /&gt;
         url: https://vault.seaoffate.net/alive&lt;br /&gt;
         icon: hl-bitwarden&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;💡 Why /alive&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
if you just ping the main URL, Dashy might get a 401 Unauthorized or a redirect, which can sometimes show up as a &amp;quot;Yellow&amp;quot; or &amp;quot;Red&amp;quot; dot even if the service is fine. The /alive path is specifically designed for health checks like this and always returns a simple 200 OK&lt;br /&gt;
&lt;br /&gt;
====Verification====&lt;br /&gt;
&lt;br /&gt;
Once started, you can verify the &amp;quot;Full-Chain TLS&amp;quot; by visiting:&lt;br /&gt;
* Internal(inside Pfsence): https://192.168.100.85 (Should show the valid seaoffate.net certificate from letsencrypt ).&lt;br /&gt;
* Internal(inside Pfsence): https://blackberry  (Assuming the internal nameserver ctns1 has the DNS entry for blackberry set should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* Internal(inside Pfsence): https://dashy.seaoffate.net (Assuming the internal nameserver ctns1 has the DNS entry for dashy set should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* Internal:(outside Pfsence) https://dashy.seaoffate.net (Assuming the DNS rewrite foe seaoffate.net on adguard set and Raisin reverse proxy rule is set, should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* External(though mobile phone Internet): https://dashy.seaoffate.net (Assuming the DNS for dashy is set on Cloudflare&#039;s control panel and dashy is proxied through Raisin it should show the Cloudflare SSL certificate).&lt;br /&gt;
When we have proved that the the dashboard works and that the login screen is displayed first we can move on to adding items to the dashboard.&lt;br /&gt;
&lt;br /&gt;
==Configuring the Dashboard==&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
	<entry>
		<id>https://wiki.seaoffate.net/index.php?title=Homelab_Dashboard&amp;diff=1498</id>
		<title>Homelab Dashboard</title>
		<link rel="alternate" type="text/html" href="https://wiki.seaoffate.net/index.php?title=Homelab_Dashboard&amp;diff=1498"/>
		<updated>2026-04-20T18:45:03Z</updated>

		<summary type="html">&lt;p&gt;Wikisailor: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
We have decided to setup a [[Home Lab]] dashboard to monitor and administer the entire estate of Virtual machines, Proxmox hosts and all of the services that we have created. initially we will use the dashy dashboard but may well change for something else if dashy proves to be to difficult or in some way unsuitable.&lt;br /&gt;
&lt;br /&gt;
==Dashy Setup==&lt;br /&gt;
&lt;br /&gt;
in the interests of security for this sensitive project we are extending your &amp;quot;Full-Chain TLS&amp;quot; SME standard to Blackberry. This ensures that even if a client bypasses the proxy (Raisin) and hits Blackberry directly on the network, the traffic is still encrypted and presents the valid *.seaoffate.net certificate. It will also mean that within the Pfsense side of the LAN any client will still meet the same secure SSL certificate system provided by Letsencrypt. 🛡️We will mount our existing SSL certificates (synced from Raisin) directly into the Dashy container and configure Dashy to serve HTTPS natively. Details of how the Certs are downloaded and installed can be found &#039;&#039;&#039;[[Letsencrypt SSL Certs |here]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Installation on Blackberry===&lt;br /&gt;
&lt;br /&gt;
🛠️ The &amp;quot;Dockge-Way&amp;quot; Setup, on our Dockge UI on Blackberry, create a new stack called dashy, and use this single, hardened configuration&lt;br /&gt;
 services:&lt;br /&gt;
   dashy:&lt;br /&gt;
     image: lissy93/dashy:latest&lt;br /&gt;
     container_name: dashy&lt;br /&gt;
     restart: unless-stopped&lt;br /&gt;
     ports:&lt;br /&gt;
       - 443:443&lt;br /&gt;
     volumes:&lt;br /&gt;
       # Use the path that we proved works:&lt;br /&gt;
       - /mnt/archive_data/docker_data/stacks/dashy/conf.yml:/app/public/conf.yml&lt;br /&gt;
       # SSL Certificates (Synced from Raisin)&lt;br /&gt;
       - /etc/nginx/ssl/seaoffate.net/fullchain.pem:/etc/ssl/certs/fullchain.pem:ro&lt;br /&gt;
       - /etc/nginx/ssl/seaoffate.net/privkey.pem:/etc/ssl/private/privkey.pem:ro&lt;br /&gt;
     environment:&lt;br /&gt;
       - NODE_ENV=production&lt;br /&gt;
       - DOCKGE_ENABLE_CONSOLE=true&lt;br /&gt;
       - SSL_PUB_KEY_PATH=/etc/ssl/certs/fullchain.pem&lt;br /&gt;
       - SSL_PRIV_KEY_PATH=/etc/ssl/private/privkey.pem&lt;br /&gt;
       - NODE_OPTIONS=--max-old-space-size=2048&lt;br /&gt;
 networks: {}&lt;br /&gt;
&lt;br /&gt;
===Post-Installation Steps ===&lt;br /&gt;
&lt;br /&gt;
====Certificate Synchronization Hook====&lt;br /&gt;
&lt;br /&gt;
Before the container will start correctly in SSL mode, we must have a basic conf.yml in the same directory as our compose.yaml. This file defines our users and our &amp;quot;Fruit Cluster&amp;quot; links. It is better to be sure that the docker app has the correct permissions for the yml, especially if it is in a non standard location.&lt;br /&gt;
 touch sudo nano /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
 sudo chown 1000:1000 /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
 sudo chmod 644 /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note&#039;&#039;&#039; we are using a non standard directory for our stacks, the more common location for the conf.yml is /opt/dockge/stacks/dashy/conf.yml&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To ensure Dashy stays updated when Raisin renews the Wildcard certs, make sure the deploy-wildcard.sh script on Raisin includes the Blackberry sync. It should have the Blackberry host in the servers list and the dashy restart in the if statements something like&lt;br /&gt;
  # Restart Dashy (Blackberry)&lt;br /&gt;
  if [ \$(docker ps -q -f name=dashy) ]; then&lt;br /&gt;
      echo &#039;  Restarting Dashy...&#039;&lt;br /&gt;
      docker restart dashy&lt;br /&gt;
  fi&lt;br /&gt;
&lt;br /&gt;
====Authentication Hardening====&lt;br /&gt;
&lt;br /&gt;
To fulfill the &amp;quot;Secure Application&amp;quot; requirement, we enable Dashy’s internal authentication. Even with a valid SSL cert, no data is visible without a login. Dashy requires a SHA-256 hash for the admin password. Run this on any terminal:&lt;br /&gt;
 echo -n &amp;quot;YourSecretPassword&amp;quot; | sha256sum&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note&#039;&#039;&#039; the quotes are only needed if there is spaces or similar in the password and the quotation marks are not part of the password&#039;&#039;&lt;br /&gt;
Take the resulting string and place it in the auth section of your conf.yml on Blackberry&lt;br /&gt;
 nano /mnt/archive_data/docker_data/stacks/dashy/conf.yml&lt;br /&gt;
A sample conf is as follows ( including the password YourSecretPassword it is assumed that the user will change the hash to some other password):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;appConfig:&lt;br /&gt;
   title: SeaOfFate Command&lt;br /&gt;
   statusCheck: true&lt;br /&gt;
   auth:&lt;br /&gt;
     enable: true&lt;br /&gt;
     enableGuestAccess: false&lt;br /&gt;
     users:&lt;br /&gt;
       - user: nigel&lt;br /&gt;
         hash: &#039;790e294c25e704e042c899bb4dbb696b9daa2ed330d270082599f8591dc62b96&#039;&lt;br /&gt;
         type: admin&lt;br /&gt;
 sections:&lt;br /&gt;
   - name: Infrastructure&lt;br /&gt;
     items:&lt;br /&gt;
       - title: Vaultwarden&lt;br /&gt;
         url: https://vault.seaoffate.net/alive&lt;br /&gt;
         icon: hl-bitwarden&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;💡 Why /alive&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
if you just ping the main URL, Dashy might get a 401 Unauthorized or a redirect, which can sometimes show up as a &amp;quot;Yellow&amp;quot; or &amp;quot;Red&amp;quot; dot even if the service is fine. The /alive path is specifically designed for health checks like this and always returns a simple 200 OK&lt;br /&gt;
&lt;br /&gt;
====Verification====&lt;br /&gt;
&lt;br /&gt;
Once started, you can verify the &amp;quot;Full-Chain TLS&amp;quot; by visiting:&lt;br /&gt;
* Internal(inside Pfsence): https://192.168.100.85 (Should show the valid seaoffate.net certificate from letsencrypt ).&lt;br /&gt;
* Internal(inside Pfsence): https://blackberry  (Assuming the internal nameserver ctns1 has the DNS entry for blackberry set should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* Internal(inside Pfsence): https://dashy.seaoffate.net (Assuming the internal nameserver ctns1 has the DNS entry for dashy set should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* Internal:(outside Pfsence) https://dashy.seaoffate.net (Assuming the DNS rewrite foe seaoffate.net on adguard set and Raisin reverse proxy rule is set, should show the valid seaoffate.net certificate from letsencrypt).&lt;br /&gt;
* External(though mobile phone Internet): https://dashy.seaoffate.net (Assuming the DNS for dashy is set on Cloudflare&#039;s control panel and dashy is proxied through Raisin it should show the Cloudflare SSL certificate).&lt;br /&gt;
When we have proved that the the dashboard works and that the login screen is displayed first we can move on to adding items to the dashboard.&lt;br /&gt;
&lt;br /&gt;
==Configuring the Dashboard==&lt;/div&gt;</summary>
		<author><name>Wikisailor</name></author>
	</entry>
</feed>