diff --git a/Spigot-Server-Patches/Add-Unix-domain-socket-support.patch b/Spigot-Server-Patches/Add-Unix-domain-socket-support.patch
new file mode 100644
index 0000000000..1a2c0f6c96
--- /dev/null
+++ b/Spigot-Server-Patches/Add-Unix-domain-socket-support.patch
@@ -0,0 +1,141 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Andrew Steinborn <git@steinborn.me>
+Date: Tue, 11 May 2021 17:39:22 -0400
+Subject: [PATCH] Add Unix domain socket support
+
+For Windows and ARM support, JEP-380 is required:
+https://inside.java/2021/02/03/jep380-unix-domain-sockets-channels/
+This will be possible as of the Minecraft 1.17 Java version bump.
+
+Tested-by: Mariell Hoversholm <proximyst@proximyst.com>
+Reviewed-by: Mariell Hoversholm <proximyst@proximyst.com>
+
+diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/network/NetworkManager.java
++++ b/src/main/java/net/minecraft/network/NetworkManager.java
+@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet<?>> {
+     // Spigot Start
+     public SocketAddress getRawAddress()
+     {
++        // Paper start - this can be nullable in the case of a Unix domain socket, so if it is, fake something
++        if (this.channel.remoteAddress() == null) {
++            return new java.net.InetSocketAddress(java.net.InetAddress.getLoopbackAddress(), 0);
++        }
++        // Paper end
+         return this.channel.remoteAddress();
+     }
+     // Spigot End
+diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer
+         this.i(dedicatedserverproperties.enforceWhitelist);
+         // this.saveData.setGameType(dedicatedserverproperties.gamemode); // CraftBukkit - moved to world loading
+         DedicatedServer.LOGGER.info("Default game type: {}", dedicatedserverproperties.gamemode);
++        // Paper start - Unix domain socket support
++        java.net.SocketAddress bindAddress;
++        if (this.getServerIp().startsWith("unix:")) {
++            if (!io.netty.channel.epoll.Epoll.isAvailable()) {
++                DedicatedServer.LOGGER.fatal("**** INVALID CONFIGURATION!");
++                DedicatedServer.LOGGER.fatal("You are trying to use a Unix domain socket but you're not on a supported OS.");
++                return false;
++            } else if (!com.destroystokyo.paper.PaperConfig.velocitySupport && !org.spigotmc.SpigotConfig.bungee) {
++                DedicatedServer.LOGGER.fatal("**** INVALID CONFIGURATION!");
++                DedicatedServer.LOGGER.fatal("Unix domain sockets require IPs to be forwarded from a proxy.");
++                return false;
++            }
++            bindAddress = new io.netty.channel.unix.DomainSocketAddress(this.getServerIp().substring("unix:".length()));
++        } else {
+         InetAddress inetaddress = null;
+ 
+         if (!this.getServerIp().isEmpty()) {
+@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer
+         if (this.getPort() < 0) {
+             this.setPort(dedicatedserverproperties.serverPort);
+         }
++        bindAddress = new java.net.InetSocketAddress(inetaddress, this.getPort());
++        }
++        // Paper end
+ 
+         this.P();
+         DedicatedServer.LOGGER.info("Starting Minecraft server on {}:{}", this.getServerIp().isEmpty() ? "*" : this.getServerIp(), this.getPort());
+ 
+         try {
+-            this.getServerConnection().a(inetaddress, this.getPort());
++            this.getServerConnection().bind(bindAddress); // Paper - Unix domain socket support
+         } catch (IOException ioexception) {
+             DedicatedServer.LOGGER.warn("**** FAILED TO BIND TO PORT!");
+             DedicatedServer.LOGGER.warn("The exception was: {}", ioexception.toString());
+diff --git a/src/main/java/net/minecraft/server/network/HandshakeListener.java b/src/main/java/net/minecraft/server/network/HandshakeListener.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/server/network/HandshakeListener.java
++++ b/src/main/java/net/minecraft/server/network/HandshakeListener.java
+@@ -0,0 +0,0 @@ public class HandshakeListener implements PacketHandshakingInListener {
+                 this.c.setProtocol(EnumProtocol.LOGIN);
+                 // CraftBukkit start - Connection throttle
+                 try {
++                    if (!(this.c.channel.localAddress() instanceof io.netty.channel.unix.DomainSocketAddress)) { // Paper - the connection throttle is useless when you have a Unix domain socket
+                     long currentTime = System.currentTimeMillis();
+                     long connectionThrottle = this.b.server.getConnectionThrottle();
+                     InetAddress address = ((java.net.InetSocketAddress) this.c.getSocketAddress()).getAddress();
+@@ -0,0 +0,0 @@ public class HandshakeListener implements PacketHandshakingInListener {
+                             }
+                         }
+                     }
++                    } // Paper - add closing bracket for if check above
+                 } catch (Throwable t) {
+                     org.apache.logging.log4j.LogManager.getLogger().debug("Failed to check connection throttle", t);
+                 }
+@@ -0,0 +0,0 @@ public class HandshakeListener implements PacketHandshakingInListener {
+                 //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above!
+                         String[] split = packethandshakinginsetprotocol.hostname.split("\00");
+                         if ( ( split.length == 3 || split.length == 4 ) && ( BYPASS_HOSTCHECK || HOST_PATTERN.matcher( split[1] ).matches() ) ) { // Paper
++                            // Paper start - Unix domain socket support
++                            java.net.SocketAddress socketAddress = c.getSocketAddress();
+                             packethandshakinginsetprotocol.hostname = split[0];
+-                            c.socketAddress = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) c.getSocketAddress()).getPort());
++                            c.socketAddress = new java.net.InetSocketAddress(split[1], socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getPort() : 0);
++                            // Paper end
+                             c.spoofedUUID = com.mojang.util.UUIDTypeAdapter.fromString( split[2] );
+                         } else
+                         {
+diff --git a/src/main/java/net/minecraft/server/network/ServerConnection.java b/src/main/java/net/minecraft/server/network/ServerConnection.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/server/network/ServerConnection.java
++++ b/src/main/java/net/minecraft/server/network/ServerConnection.java
+@@ -0,0 +0,0 @@ public class ServerConnection {
+         this.c = true;
+     }
+ 
++    // Paper start
+     public void a(@Nullable InetAddress inetaddress, int i) throws IOException {
++        bind(new java.net.InetSocketAddress(inetaddress, i));
++    }
++    public void bind(java.net.SocketAddress address) throws IOException {
++    // Paper end
+         List list = this.listeningChannels;
+ 
+         synchronized (this.listeningChannels) {
+@@ -0,0 +0,0 @@ public class ServerConnection {
+             LazyInitVar lazyinitvar;
+ 
+             if (Epoll.isAvailable() && this.e.l()) {
++                if (address instanceof io.netty.channel.unix.DomainSocketAddress) {
++                    oclass = io.netty.channel.epoll.EpollServerDomainSocketChannel.class;
++                } else {
+                 oclass = EpollServerSocketChannel.class;
++                }
+                 lazyinitvar = ServerConnection.b;
+                 ServerConnection.LOGGER.info("Using epoll channel type");
+             } else {
+@@ -0,0 +0,0 @@ public class ServerConnection {
+                     ((NetworkManager) object).setPacketListener(new HandshakeListener(ServerConnection.this.e, (NetworkManager) object));
+                     io.papermc.paper.network.ChannelInitializeListenerHolder.callListeners(channel); // Paper
+                 }
+-            }).group((EventLoopGroup) lazyinitvar.a()).localAddress(inetaddress, i)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit
++            }).group((EventLoopGroup) lazyinitvar.a()).localAddress(address)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit // Paper
+         }
+     }
+ 
diff --git a/Spigot-Server-Patches/Add-Velocity-IP-Forwarding-Support.patch b/Spigot-Server-Patches/Add-Velocity-IP-Forwarding-Support.patch
index f06769b490..d75f2ceb46 100644
--- a/Spigot-Server-Patches/Add-Velocity-IP-Forwarding-Support.patch
+++ b/Spigot-Server-Patches/Add-Velocity-IP-Forwarding-Support.patch
@@ -268,7 +268,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                return;
 +            }
 +
-+            this.networkManager.socketAddress = new java.net.InetSocketAddress(com.destroystokyo.paper.proxy.VelocityProxy.readAddress(buf), ((java.net.InetSocketAddress) this.networkManager.getSocketAddress()).getPort());
++            java.net.SocketAddress listening = this.networkManager.getSocketAddress();
++            int port = 0;
++            if (listening instanceof java.net.InetSocketAddress) {
++                port = ((java.net.InetSocketAddress) listening).getPort();
++            }
++            this.networkManager.socketAddress = new java.net.InetSocketAddress(com.destroystokyo.paper.proxy.VelocityProxy.readAddress(buf), port);
 +
 +            this.setGameProfile(com.destroystokyo.paper.proxy.VelocityProxy.createProfile(buf));
 +
diff --git a/Spigot-Server-Patches/Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/Spigot-Server-Patches/Add-handshake-event-to-allow-plugins-to-handle-clien.patch
index a512e8e811..c4e6764d91 100644
--- a/Spigot-Server-Patches/Add-handshake-event-to-allow-plugins-to-handle-clien.patch
+++ b/Spigot-Server-Patches/Add-handshake-event-to-allow-plugins-to-handle-clien.patch
@@ -27,8 +27,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                boolean handledByEvent = false;
 +                // Try and handle the handshake through the event
 +                if (com.destroystokyo.paper.event.player.PlayerHandshakeEvent.getHandlerList().getRegisteredListeners().length != 0) { // Hello? Can you hear me?
-+                    java.net.InetSocketAddress socketAddress = (java.net.InetSocketAddress) this.getNetworkManager().socketAddress;
-+                    com.destroystokyo.paper.event.player.PlayerHandshakeEvent event = new com.destroystokyo.paper.event.player.PlayerHandshakeEvent(packethandshakinginsetprotocol.hostname, socketAddress.getAddress().getHostAddress(), !proxyLogicEnabled);
++                    java.net.SocketAddress socketAddress = this.getNetworkManager().socketAddress;
++                    String hostnameOfRemote = socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getHostString() : InetAddress.getLoopbackAddress().getHostAddress();
++                    com.destroystokyo.paper.event.player.PlayerHandshakeEvent event = new com.destroystokyo.paper.event.player.PlayerHandshakeEvent(packethandshakinginsetprotocol.hostname, hostnameOfRemote, !proxyLogicEnabled);
 +                    if (event.callEvent()) {
 +                        // If we've failed somehow, let the client know so and go no further.
 +                        if (event.isFailed()) {
@@ -39,7 +40,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                        }
 +
 +                        if (event.getServerHostname() != null) packethandshakinginsetprotocol.hostname = event.getServerHostname();
-+                        if (event.getSocketAddressHostname() != null) this.getNetworkManager().socketAddress = new java.net.InetSocketAddress(event.getSocketAddressHostname(), socketAddress.getPort());
++                        if (event.getSocketAddressHostname() != null) this.getNetworkManager().socketAddress = new java.net.InetSocketAddress(event.getSocketAddressHostname(), socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getPort() : 0);
 +                        this.getNetworkManager().spoofedUUID = event.getUniqueId();
 +                        this.getNetworkManager().spoofedProfile = gson.fromJson(event.getPropertiesJson(), com.mojang.authlib.properties.Property[].class);
 +                        handledByEvent = true; // Hooray, we did it!