# How to Run a Minecraft Server: Multiple Approaches

## Background

In [An intro to Minecraft mods](https://blog.saleshorse.org/an-intro-to-minecraft-mods#heading-fabric), I outline my reasons for choosing the Fabric framework over Forge. Continuing with that same reasoning, this post will be outlining multiple approaches for running a Minecraft server using Fabric (although at a high level, the concepts should still apply to Forge).

You may want to do some research beforehand to determine which mods you want to run on your server, since Fabric mods will only run on a Fabric server, and Forge mods will only run on a Forge server.

If you're not sure what a Minecraft server is, you can simply think of it as a place to house Minecraft mods. To get a better idea of how a server fits into modding in general, read the [Fabric Server section](https://blog.saleshorse.org/an-intro-to-minecraft-mods#heading-fabric-server) of the aforementioned post.

## Overview

You might be wondering where the "multiple approaches" bit comes in, since we are only focusing on Fabric. We'll be covering the following ways to host a Fabric server:

* local machine
    
    * Windows
        
    * Linux/MacOS
        
* VPS
    

Regardless of where the server is hosted, it can be invoked (or "spun up") in multiple ways:

* raw commands in a shell
    
* running a script file
    
* running the server in a Docker container
    

## Choosing a server location

In the [Development Environment section](https://blog.saleshorse.org/an-intro-to-minecraft-mods#heading-development-environment) of the first post, we covered the fact that your development environment matters, in terms of which computer you use. Conversely, the computer you choose to use as your server doesn't matter at all -- so long as it has the proper version of Java and enough RAM to run Minecraft.

### Separate machine vs local machine

Speaking of RAM, that is one reason you might choose to run your server on a separate computer; the default amount of RAM allocated to the Minecraft server is 2GB, which your computer may not have to spare.

Even if RAM isn't an issue for you, you may still want a separate machine for other reasons -- a big one being availability; if you want your server to be accessible round-the-clock, you likely want a separate machine. Otherwise, your server goes down if your computer shuts off or loses network connectivity.

On the other hand, if your server needs are more casual and constant availability isn't a concern, then running the server locally (from your main machine) might be enough for you.

### A new computer isn't necessary

You also might be thinking, "I can't afford to buy another computer to run a server on". If that's the case, you could explore these options:

* using an old computer
    
* buying a Raspberry Pi (can be found for less than $100)
    
* using a Virtual Private Server (monthly cost depending on usage and server specs)
    

### Docker

Docker might be a good option if you want to be able to reuse the same server configuration on multiple devices, or if you don't want to alter an existing Java configuration. Here are a few things to note about running a server in a Docker container:

* it will still consume RAM on whatever computer is running the container
    
* no Java configuration is required
    
    * Java is automatically installed in the container
        
* Docker containers don't "care" where they are run from
    
    * you can bundle the container's configuration into a file on your local machine
        
    * that same file can be used to run an identical container on a separate machine (regardless of that machine's OS)
        
* Docker can run from
    
    * your local machine
        
    * another physical machine
        
        * an old laptop
            
        * a Raspberry Pi
            
    * a Virtual Private Server
        
    * ...or any other hardware that supports Docker.
        

Here's an example of when you might want to use Docker:

You are testing out a Minecraft server configuration with multiple mods, and multiple custom game settings. You're testing this configuration out on your laptop, but you want to be able to recreate the configuration on another machine without having to install each mod and enable each custom game setting all over again.

This is a great reason to use Docker. At a high level, the configuration would look something like this:

* find and download a Docker *image* that is preconfigured for running a Minecraft server
    
    * think of the image as the blueprint for the container
        
* use the image to run a *container*
    
    * the image's blueprint is used to construct and "run" the container
        
    * think of a container as a self-contained environment for which to run software
        
* load the mods you want to test into the container via a *volume*
    
    * a volume is a way to link file storage between the *host machine* and the container
        
        * the host machine is the computer that Docker is installed on
            
    * the volume is where the `/mods` folder will live
        
* once you've decided on the game settings and mods you want to use, put instructions on how the container should be run in a `docker-compose.yml` file
    
    * Docker Compose files describe the specifics of how the server container be run, such as
        
        * the version of Minecraft to use
            
        * which user(s) to grant operator permissions
            
        * game settings (max players, spawn point, mobs, etc.)
            

We'll illustrate these concepts with examples later in the [Running a Server with Docker](https://blog.saleshorse.org/how-to-run-a-minecraft-server-multiple-approaches#heading-running-a-server-with-docker) section.

## Running a Server

### Java Prerequisite

If you plan on running a server on a machine other than your own, make sure to install Java on that machine, following the [instructions provided by Fabric](https://fabricmc.net/wiki/player:tutorials:java:windows).

If you're using Docker, make sure the image you're using has the correct version of Java. The image likely has a way to specify a Java version with a [tag](https://docs.docker.com/engine/reference/commandline/tag/) for the image.

If you're using Linux for your server, the instructions Fabric provides for setting up Java are fairly basic. For more detailed instructions, see [Installing Java on Ubuntu](https://blog.saleshorse.org/installing-java-on-ubuntu-without-breaking-your-shell).

### Loading a mod onto the server

For mods to work on the server, we need to make sure that our Minecraft client has those same mods. More specifically, that means:

* you have an installation of the Fabric launcher (client) whose version matches the Minecraft version of your server
    
    * this is the launcher you select when you open the Minecraft application on your computer
        
* the `/mods` folder for your Fabric launcher installation contains:
    
    * the `.jar` file for the proper version of the Fabric API
        
    * a `.jar` file for each mod
        
* the `/mods` folder for your Fabric server must contain the same `.jar` files as the `/mods` folder in the Fabric launcher
    

In other words, the `/mods` folder within your Fabric launcher *client* should have the *same contents* as the `/mods` folder on your Fabric *server*. If you want to read more about the reasoning, check out the [Fabric docs](https://fabricmc.net/wiki/tutorial:side) on this topic.

* once the `/mods` folders match on the client and server, launch the server
    
* once the server is running, grant `op` (operator) permissions to necessary player(s)
    
* connect to the server using the [Connecting to your server](https://blog.saleshorse.org/how-to-run-a-minecraft-server-multiple-approaches#heading-connecting-to-your-server) instructions below
    
* verify that you can use the mod
    

Approach-specific instructions are detailed below.

### Running a Server on Linux/MacOS

This is perhaps the most accessible option since it can be run from:

* a machine running Linux
    
    * Raspberry Pi
        
    * VPS
        
* a machine running MacOS
    

Here we'll follow instructions from the [Fabric wiki](https://fabricmc.net/wiki/player:tutorials:install_server), and walk through them as we go.

If you've been following along, you should already have Java installed. The next step is to go to the [server download page](https://fabricmc.net/use/server/) and download the relevant version:

```bash
# make a directory for the server
mkdir fabric-server
cd fabric-server

# download the file to our fabric-server directory
curl -OJ https://meta.fabricmc.net/v2/versions/loader/1.19.4/0.14.19/0.11.2/server/jar

# confirm the download worked
ls
# output
fabric-server-mc.1.19.4-loader.0.14.19-launcher.0.11.2.jar
```

Now that we have the server's `.jar` file downloaded, we can use the command supplied on the download page to launch the server using that `.jar` file:

```bash
# launch the server, allocating 2GB RAM
java -Xmx2G -jar fabric-server-mc.1.19.4-loader.0.14.19-launcher.0.11.2.jar nogui
```

We get an error, which is expected because we need to accept the EULA:

```bash
[21:10:21] [main/ERROR]: Failed to load properties from file: server.properties
[21:10:21] [main/WARN]: Failed to load eula.txt
[21:10:21] [main/INFO]: You need to agree to the EULA in order to run the server. Go to eula.txt for more info.
```

If we inspect the contents of our server folder, we can see that files and directories have been generated as a result of attempting running the server. Among these is the file `eula.txt`:

```bash
# in fabric-server directory
ls -la # press enter

# output
drwxr-xr-x  4 idev idev   4096 Jun 12 21:10 .fabric
-rw-r--r--  1 idev idev    158 Jun 12 21:10 eula.txt
-rw-r--r--  1 idev idev 155095 Jun 12 21:09 fabric-server-mc.1.19.4-loader.0.14.19-launcher.0.11.2.jar
drwxr-xr-x  8 idev idev   4096 Jun 12 21:10 libraries
drwxr-xr-x  2 idev idev   4096 Jun 12 21:10 logs
drwxr-xr-x  2 idev idev   4096 Jun 12 21:10 mods
-rw-r--r--  1 idev idev   1272 Jun 12 21:10 server.properties
drwxr-xr-x  3 idev idev   4096 Jun 12 21:10 versions
```

Now we can open that file with our preferred text editor and change `false` to `true`:

```bash
vim eula.txt

# inside eula.txt
eula=true
# save and exit eula.txt
```

Now that we've agreed to the EULA, we can re-run the command to launch the server:

```bash
# launch the server, allocating 2GB RAM
java -Xmx2G -jar fabric-server-mc.1.19.4-loader.0.14.19-launcher.0.11.2.jar nogui
```

The server starts up this time with no errors:

```bash
[21:15:16] [Worker-Main-2/INFO]: Preparing spawn area: 91%
[21:15:16] [Worker-Main-2/INFO]: Preparing spawn area: 94%
[21:15:17] [Worker-Main-5/INFO]: Preparing spawn area: 97%
[21:15:17] [Server thread/INFO]: Time elapsed: 28858 ms
[21:15:17] [Server thread/INFO]: Done (35.063s)! For help, type "help"
```

Now that the server is running, we can click into the terminal and type `op your_player_name`

```bash
[14:24:08] [Server thread/INFO]: Time elapsed: 8357 ms
[14:24:08] [Server thread/INFO]: Done (10.491s)! For help, type "help"
op awesomeminecraftplayer42023
[14:25:01] [Server thread/INFO]: Made maddoxchunk a server operator
```

### Running a Server on Windows

The [Fabric](https://fabricmc.net/wiki/player:tutorials:server:windows) instructions do a pretty good job of walking through this one, but we'll go through the steps here anyway (starting with *STEP 3: Install Fabric in the Server Folder*):

* go [here](https://fabricmc.net/use/installer/) and click the 'download for Windows' button
    
* run the file
    
* **select the 'Server' tab**
    
* select the version and install the location
    
    * the Minecraft version should match the Minecraft version of the mod(s) you want to use
        
    * note that this file location has nothing to do with your installation of Minecraft
        
* press 'Install'
    
* click 'Download server jar'
    
* click 'Generate'
    
* open the folder location where you saved the server to
    
* run the `start.bat` file
    
* you'll get an error about the EULA
    
* close the terminal
    
* open `eula.txt` in the server folder that has the `start.bat` file
    
* change `false` to `true` in `eula.txt`
    
* save and exit the file
    
* run `start.bat` again
    
* click into the terminal with the server running and type `op your_player_name` to grant operator permissions
    

### Running a Server with Docker

I won't go over installing Docker, since their [official docs](https://docs.docker.com/engine/install/) should be enough to get you there.

It's worth mentioning that once you have Docker installed, the steps below will work the same (more or less), regardless of your operating system.

#### Run a Vanilla Minecraft server in a container

Once you've got Docker installed, it's time to download and run a Minecraft server image.

* start by going to the [documentation for the Docker image](https://docker-minecraft-server.readthedocs.io/en/latest/) we're using
    
* run the listed command
    
    * `docker run -d -it -p 25565:25565 -e EULA=TRUE itzg/minecraft-server`
        
    * this runs the container in the background so that our terminal is free to run other commands
        
    * confirm the container is running with `docker ps`
        
* copy the `CONTAINER ID` from the `docker ps` command
    
* run `docker stop <CONTAINER ID>` to stop the container
    
* run `docker ps` again to confirm the container is not running
    

#### Run a Fabric Minecraft server in a container

The `docker` command above allowed us to run a "vanilla" Minecraft server. However, we are interested in running a Fabric server, so we consult the [Types and platforms documentation](https://docker-minecraft-server.readthedocs.io/en/latest/types-and-platforms/).

From here we can select 'Fabric' from the menu on the left. We can see a command that instructs us on how to run a Fabric server by using the `-e TYPE=FABRIC` flag. However, there is something else that's different about this command: it's mounting a volume with `-v /path/on/host:/data`. Before we run this command, we need to set up that directory on our host machine (the one running Docker).

#### Mounting a data directory

If we head to the [Data directory](https://docker-minecraft-server.readthedocs.io/en/latest/data-directory/) documentation, we get some instructions on how to do this.

Let's try running a container with an attached data volume, using the supplied command from the [Fabric section of the image docs](https://docker-minecraft-server.readthedocs.io/en/latest/types-and-platforms/server-types/fabric/):

```bash
mkdir mc-data

docker run -d -v ./mc-data:/data \
    -e TYPE=FABRIC \
    -p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
```

Okay, so we've started a container and mounted the volume, but how do we use it?

It's a bit difficult to picture right now, since we're running the container as a background process with the `-d` flag. Let's try running it again without that flag and see what happens:

```bash
# first, remove/stop the container
docker rm mc

# run the same command without the -d flag
docker run -v ./mc-data:/data \
    -e TYPE=FABRIC \
    -p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server

# output
[init] Running as uid=1000 gid=1000 with /data as 'drwxrwxr-x 2 1000 1000 4096 Jun 15 11:12 /data'
... # (more output)
[init] ERROR: version lookup failed:
```

This isn't an error with the volume. We would get the same error if we ran the command without the `-v flag`. The only reason we didn't see the error before is that we ran the process in the background, so the output wasn't visible.

This error is because we need to specify a Fabric/Minecraft version for the container to run.

Let's try it again, this time using the appropriate flags to specify the version:

```bash
docker rm mc

docker run -v ./mc-data:/data \
    -e TYPE=FABRIC \
    -e VERSION=1.19.4 \
    -p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
```

We still get an error, but this time it's different:

```bash
[init] ERROR failed to install Fabric launcher from 1.19.4, LATEST, LATEST
```

This is yet another misleading error message. In my case, it was happening due to an issue with WSL2. The issue is resolved by deleting the `~/.docker/config.json` file.

If you encountered the error above, go ahead and delete the `config.json` file, then run the commands again to make sure it works:

```bash
docker rm mc

docker run -v ./mc-data:/data \
    -e TYPE=FABRIC \
    -e VERSION=1.19.4 \
    -p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
```

Now that we know we can get the server running, it's time to add our mod.

#### Loading mods onto the server

Looking again at the [Data directory documentation](https://docker-minecraft-server.readthedocs.io/en/latest/data-directory/), we can see that the `/mods` folder lives inside the `/data` directory, which we have created as `mc-data` on our host machine.

Speaking of the data directory, if we inspect the contents of `mc-data`, we can see that the folder is no longer empty since we have successfully run the server:

```bash
# stop the server if it's still running using CTRL + C
ls mc-data

#output
banned-ips.json      fabric-server-mc.1.19.4-loader.0.14.21-launcher.0.11.2.jar  ops.json           whitelist.json
banned-players.json  libraries                                                   server.properties  world
crash-reports        logs                                                        usercache.json
eula.txt             mods                                                        versions
```

Recall from [Loading a mod onto the server](https://blog.saleshorse.org/how-to-run-a-minecraft-server-multiple-approaches?#heading-loading-a-mod-onto-the-server) that the `/mods` folder on our server should match the `/mods` folder in our Fabric launcher installation. As such, we copy the contents of that folder to our data directory for the container

```bash
# copy the contents of the Fabric 
# launcher's /mods folder into the mc-data/mods folder
cp -a /path/to/fabric/launcher/mods .mc-data/mods
```

Now we are ready to run our server again:

```bash
docker rm mc

docker run -v ./mc-data:/data \
    -e TYPE=FABRIC \
    -e VERSION=1.19.4 \
    -p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
```

Go ahead and connect to your server using the [instructions](https://blog.saleshorse.org/how-to-run-a-minecraft-server-multiple-approaches#heading-connecting-to-your-server) below.

The game loads up when we connect, but we have a problem -- we aren't able to run commands. Normally, we could just go to our terminal and `op` our player, but things work a bit differently with Docker. Since we are running the server in a container, we don't have direct access to the terminal like we do when we run the server directly in the operating system.

So how do we issue commands to our Docker container? Enter `RCON`.

#### RCON

`RCON` is short for Remote Control, and allows Minecraft commands to be issued *remotely*.

Okay, but... how do we use it?

Thankfully, the Docker image we're using includes `rcon-cli`. Let's see it in action:

```bash
# stop the container (if running)
docker stop mc

# start the container again
docker start mc
```

Before we can run `rcon-cli`, we need to wait for server to completely load, since `RCON` does not become enabled until that point. When you see the following message in the terminal, you're ready to use `rcon-cli`:

```bash
[03:28:23] [Server thread/INFO]: Done (8.096s)! For help, type "help"
[03:28:23] [Server thread/INFO]: Starting remote control listener
[03:28:23] [Server thread/INFO]: Thread RCON Listener started
[03:28:23] [Server thread/INFO]: RCON running on 0.0.0.0:25575
```

Once the `RCON` service has started, we can open a new terminal window and use `rcon-cli`:

```bash
# replace your_player_name with the actual name of your player
docker exec mc rcon-cli op your_player_name

# output
Made your_player_name a server operator
```

Now that you are an operator, you can use commands in Minecraft. Go ahead and use the appropriate command(s) to test out your mod (if applicable).

#### Docker Compose

When I originally explained the use cases for Docker, a big selling point was the portability, and the ability to reuse configurations. So far, we haven't seen how Docker can achieve that. We ran a bunch of commands, and even hit some errors in the process.

How can a workflow like that be reusable?

The answer is that it can't, and that's where Docker Compose comes into play.

Now that we have a *working* configuration, we can package that configuration into a `docker-compose.yml` file so that we don't have to remember the commands. Instead, we can just point Docker to the `docker-compose.yml` file.

Let's go through the [instructions](https://docker-minecraft-server.readthedocs.io/en/latest/#using-docker-compose):

* first install Docker Compose by following the [instructions here](https://docs.docker.com/compose/install/).
    
* make a new directory and change into it
    
    ```bash
    mkdir mc-compose 
    cd mc-compose
    ```
    
* create a `docker-compose.yml` file and put the following in it
    

> note that the file below is slightly different from the file linked in the documentation (we added the `VERSION` and `TYPE` environment variables)
> 
> also note that **indentation matters** in a `.yml` file

* ```bash
        version: "3.8"
        
        services:
          mc:
            image: itzg/minecraft-server
            tty: true
            stdin_open: true
            ports:
              - "25565:25565"
            environment:
              EULA: "TRUE"
              VERSION: "1.19.4"
              TYPE: "FABRIC"
            volumes:
              # attach the relative directory 'data' to the container's /data path
              - ./data:/data
    ```
    

#### Using an `.env` file

To make things even more reusable, we can use an `.env` file located in the same folder as our `docker-compose.yml` file.

```bash
vim .env

# .env
VERSION=1.19.4
SERVER_TYPE=FABRIC
DATA_DIR=./mc-data
```

Now we can update our `docker-compose.yml`:

```bash
# docker-compose.yml
version: "3.8"

services:
  mc:
    image: itzg/minecraft-server
    container_name: mc
    tty: true
    stdin_open: true
    ports:
      - "25565:25565"
    environment:
      EULA: "TRUE"
      VERSION: "${VERSION}"
      TYPE: "${SERVER_TYPE}"
    volumes:
      # attach the relative directory 'data' to the container's /data path
      - "${DATA_DIR}:/data"
```

Run the server with `docker compose up` to make sure the new config works.

#### Automating RCON

Remember how we had to wait for the server to spin up before we could use `rcon-cli`? That was kind of annoying. It would be nice if there were a way to automate this.

Thankfully, someone made a pull request, and some [new commands were added](https://github.com/itzg/docker-minecraft-server/pull/1391) to the image. These commands allow `rcon-cli` to run automatically, either when the server starts, or when the game client connects to the server.

We'll keep things simple and just automate the provisioning of operator permissions. In the `docker-compose.yml` file below, you'll notice a new `RCON_CMDS_STARTUP` property under `environment`:

```bash
# docker-compose.yml
version: "3.8"

services:
  mc:
    image: itzg/minecraft-server
    container_name: mc
    tty: true
    stdin_open: true
    ports:
      - "25565:25565"
    environment:
      EULA: "TRUE"
      VERSION: "${VERSION}"
      TYPE: "${SERVER_TYPE}"
      RCON_CMDS_STARTUP:  |-
        /op your_username_goes_here
    volumes:
      # attach the relative directory 'data' to the container's /data path
      - "${DATA_DIR}:/data"
```

Go ahead and run the container with `docker compose up`. If you get an error like `Additional property RCON_CMDS_STARTUP is not allowed`, the issue is likely that something isn't indented properly. Go back into the file and make sure the new command is indented one level in from `environment`.

But remember, we want this `docker-compose.yml` file to be as reusable as possible. Once it's complete, any changes that we need to make to the configuration should be done via the `.env` file. Let's put our player name into the `.env` file:

```bash
vim .env

# .env
VERSION=1.19.4
SERVER_TYPE=FABRIC
DATA_DIR=/mnt/c/Users/iDev/fabric-1.19.4-client/
OP_PLAYER=your_username_goes_here
```

Now we can adjust our `docker-compose.yml` file accordingly:

```bash
# docker-compose.yml
version: "3.8"

services:
  mc:
    image: itzg/minecraft-server
    container_name: mc
    tty: true
    stdin_open: true
    ports:
      - "25565:25565"
    environment:
      EULA: "TRUE"
      VERSION: "${VERSION}"
      TYPE: "${SERVER_TYPE}"
      RCON_CMDS_STARTUP:  |-
        /op ${OP_PLAYER} # note that there are no quotes in this command
    volumes:
      # attach the relative directory 'data' to the container's /data path
      - "${DATA_DIR}:/data"
```

Note that the syntax is slightly different for this command, compared to the others. There are no quotes around the command. Using quotes will cause an error.

It's also possible to specify more than one player, but the error handling still needs to be worked out. This means that if you make a typo in one player's name, or one of the players doesn't exist, the entire command will fail.

If you're interested in experimenting with this, the syntax for specifying multiple players is as follows:

```bash
# .env
# OP_PLAYERS=player1:player2:player3 # this will fail; no valid players
OP_PLAYERS=your_user_name_goes_here:player2 # this will fail; at least one invalid player
```

#### Reusing a Docker config

So far, we've seen how using Docker Compose can save us from having to type long complicated commands. We can take it a step further and place our `docker-compose.yml` file on another machine so that it can run the same container with the same configuration.

First things first, we'll copy the file from our local machine over to a Virtual Private Server that has Docker installed. Also note that a user named `mc-admin` has already been created on the VPS:

```bash
# in mc-compose folder on local machine
# make sure to add the '/' at the end of vps-mc!
rsync -a ./docker-compose.yml digitalocean.minecraft:/home/mc-admin/vps-mc/
```

If you're unfamiliar with `rsync`, here is what the command above does:

* takes the `docker-compose.yml` file in our current directory on the local machine
    
* uses SSH behind the scenes to log into the VPS (`digitalocean.minecraft`)
    
    * an SSH config file obscures the username and IP of the Digital Ocean VPS we're logging into
        
    * to execute without a SSH config file:
        
        * replace `digitalocean.minecraft` with `user@ip.address.of.vps`
            
* creates a directory `vps-mc/` on the VPS, under the existing `mc-admin` user's `/home` directory
    
    * this is why the `/` is important at the end of the command
        
    * without the `/`, `vps-mc` will be created as a file instead of a folder
        
* places the `docker-compose.yml` file in the `/home/mc-admin/vps-mc` directory of the VPS
    

Since I've previously configured `ssh`, I don't need to supply a username and password when I run the command above.

If you haven't configured `ssh`, it would look more like this:

```bash
# we need to specify username@server
rsync -a  ./docker-compose.yml mc-admin@docker.vps.ip:/home/mc-admin/vps-mc/
```

If you want to learn how to simply your `ssh` flow like I have, make sure to check out my [Managing SSH Keys post](https://blog.saleshorse.org/managing-multiple-ssh-keys-on-both-ends).

Before we run the server, we need to transfer over a few more files and folders:

```bash
rsync ./.env digitalocean.minecraft:/home/mc-admin/vps-mc/
rsync -a --mkpath ./mc-data/mods/ digitalocean.minecraft:/home/mc-admin/vps-mc/mc-data/mods/
```

Now we're ready to run the server on the VPS:

```bash
ssh digitalocean.minecraft

# now in vps
cd vps-mc
docker compose up

# output
permission denied while trying to connect to the Docker daemon socket at 
unix:///var/run/docker.sock: 
Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json?all=1&filters=%7B%22label%22%3A%7B%22com.docker.compose.config-hash%22%3Atrue%2C%22com.docker.compose.project%3Dpi-mc%22%3Atrue%7D%7D": 
dial unix /var/run/docker.sock: connect: permission denied
```

Okay, so we got a permissions error. No biggie, this is a pretty common thing to run into with Docker. I had already configured it on my local machine, but we need to set it up on the VPS.

#### Enabling rootless Docker

Yes, prefixing Docker Compose command with `sudo` would fix our issue, but running Docker as root goes against best practices, so we're going to do it the proper way:

You can follow along with this step by viewing the [Docker documentation](https://docs.docker.com/engine/security/rootless/#:~:text=Rootless%20Docker%20in%20Docker,%3A%2Ddind%20.&text=The%20docker%3A%2D,root%20user%20(UID%201000).).

* first we'll start by updating our package manager
    
    * `sudo apt-get update && sudo apt-get upgrade`
        
* next we'll install the package that Docker tells us we need
    
    * `sudo apt-get install uidmap`
        
* follow the instructions under **Distribution-specific hint**
    
    * `sudo apt-get install -y dbus-user-session`
        
    * the package is already installed, so no need to log out/back in
        
* follow the instructions under the **Install** section
    
    * `dockerd-rootless-setuptool.sh install`
        
    * receive `command not found` error
        
    * continue following instructions: `sudo apt-get install -y docker-ce-rootless-extras`
        
    * received another error: `Unable to locate package docker-ce-rootless-extras`
        
    * switch to the *Without Packages* tab and run `curl -fsSL https://get.docker.com/rootless | sh`
        

The installation was successful, but we have some output to read through:

```bash
# output from the install script
[INFO] Installed docker.service successfully.
[INFO] To control docker.service, run: `systemctl --user (start|stop|restart) docker.service`
[INFO] To run docker.service on system startup, run: `sudo loginctl enable-linger sharif`

[INFO] Creating CLI context "rootless"
Successfully created context "rootless"
[INFO] Using CLI context "rootless"
Current context is now "rootless"

[INFO] Make sure the following environment variable(s) are set (or add them to ~/.bashrc):
export PATH=/usr/bin:$PATH

[INFO] Some applications may require the following environment variable too:
export DOCKER_HOST=unix:///run/user/1000/docker.sock
```

Going through the sections of output one by one:

* since I want Docker to run when the system starts, I run the provided command
    
    * `sudo loginctl enable-linger sharif`
        
* I need to set both the `PATH` and `DOCKER_HOST` environment variables
    
    * I'm using `zsh` and not `bash`, so environment variables are set differently
        
    * I refer to a [previous blog post of mine](https://blog.saleshorse.org/installing-java-on-ubuntu-without-breaking-your-shell#shell-environment-table) to set the environment variables at the profile level
        

Now we should be able to run `docker compose up` from our `vps-mc` directory again without getting a permissions error.

## Connecting to your server

On our computer with Minecraft installed, we can open our Minecraft Launcher, and confirm that we can connect to the server.

* select the Fabric Launcher installation
    
    * make sure the version of Minecraft for the launcher aligns with the version of Minecraft for your server
        
* when the game loads, select 'Multiplayer'
    
* accept the warning about third-party online play
    
* select 'Direct Connection'
    
* depending on how you set up your server, you'll need to enter the hostname accordingly
    
    * local server: `localhost:25565`
        
    * VPS: `<IP of your server>:25565`
        
* click 'Join Server'
    

## Resources

* [Install Docker in WSL2 without Docker Desktop](https://nickjanetakis.com/blog/install-docker-in-wsl-2-without-docker-desktop)
    
* [Run Docker as a non-root user](https://docs.docker.com/engine/security/rootless/)
    
* [Docker volumes documentation](https://docs.docker.com/storage/volumes/)
    
* [Docker `.env` file documentation](https://docs.docker.com/compose/environment-variables/env-file/)
    
* [Minecraft server Docker image documentation](https://docker-minecraft-server.readthedocs.io/en/latest/)
    
* [Fabric server `.jar` download (Linux/MacOS)](https://fabricmc.net/use/server/)
    
* [Fabric server installer for Windows](https://fabricmc.net/use/installer/)
    
* [Fabric client/server patterns](https://fabricmc.net/wiki/tutorial:side)
    
* [Install Java on Windows](https://fabricmc.net/wiki/player:tutorials:java:windows)
    
* [Installing Java on Ubuntu](https://blog.saleshorse.org/installing-java-on-ubuntu-without-breaking-your-shell)
    
* [An Intro to Minecraft Mods](https://blog.saleshorse.org/an-intro-to-minecraft-mods)
