Modded Minecraft Server (Forge) with Twingate
Host a private Forge modded Minecraft server and keep it off the public internet.
This guide uses Docker Compose and works on any OS. For a native install on a dedicated Linux server, see the Linux version. See all Minecraft guides to compare editions, or jump to vanilla Java or Bedrock.
Overview
A modded Minecraft server adds extra setup on top of a vanilla server. The server needs Forge installed, mods loaded, and enough RAM to run them. Every player connecting must have the same mods (and same versions) installed on their client, or the server will reject the connection.
The best way to keep server and players in sync is to use a CurseForge modpack. The server downloads and installs the pack automatically from a URL, and players install the same pack through a launcher. No manual file copying.
If you prefer to hand-pick mods instead of using a modpack, this guide covers that too.
The Twingate setup is identical to a vanilla server. Docker Compose runs the Forge server and a Twingate Connector side by side, and players connect using the server’s private IP address through the Twingate Client.
Architecture
[Player's Device] ↓ Twingate Client[Twingate Cloud] ↓[Twingate Connector] ↓[Forge Server — port 25565]Prerequisites
- A machine with at least 4 GB of RAM, 2 CPU cores, and 20 GB of free disk space. Linux, macOS, and Windows are all supported.
- Docker Engine and Docker Compose installed. If not yet installed, follow Docker’s official install guide.
- A Twingate account with access to the Admin Console. Sign up for free if you do not have one.
- Terminal access to the machine.
How much RAM?
It depends on the modpack. Small packs (20-50 mods) run fine on 4 GB. Large kitchen-sink packs (200+ mods like All the Mods or RLCraft) need 6-8 GB. Check the modpack’s description for recommended specs, and raise the MEMORY value in docker-compose.yml if needed. If the server crashes on startup with an out-of-memory error, increase MEMORY and make sure the host has that much RAM free. The JVM and Forge add overhead on top of the heap, so a 6G heap can use 7 GB or more in practice. The Twingate Connector adds under 256 MB on top.
Step 1: Create a Remote Network and Generate Connector Tokens
Follow Step 1 in the vanilla Minecraft guide to create a Remote Network and generate Connector tokens, then return here.
Step 2: Deploy the Forge Server and Connector
There are two ways to set up the server: using a CurseForge modpack (recommended) or manually installing individual mods.
Option A: CurseForge Modpack (Recommended)
This is the recommended path. The Docker image downloads the modpack, installs Forge, and configures everything from a single URL.
- Open a terminal on the machine.
- Create a project directory and navigate into it:
# macOS / Linuxmkdir -p ~/minecraft-forge && cd ~/minecraft-forge
# Windows (PowerShell)New-Item -ItemType Directory -Force ~\minecraft-forge; cd ~\minecraft-forge-
Get your CurseForge API key. Go to console.curseforge.com, create an account if needed, and generate an API key. This is free.
-
Find your modpack on curseforge.com/minecraft/modpacks. Copy the page URL (e.g.,
https://www.curseforge.com/minecraft/modpacks/all-the-mods-10). -
Create a file named
docker-compose.yml:
services: minecraft: image: itzg/minecraft-server:latest container_name: forge-server environment: EULA: "TRUE" TYPE: "AUTO_CURSEFORGE" CF_PAGE_URL: "https://www.curseforge.com/minecraft/modpacks/all-the-mods-10" CF_API_KEY: "<YOUR_CURSEFORGE_API_KEY>" MEMORY: "6G" MAX_PLAYERS: "10" MOTD: "Private Modded Server" volumes: - ./data:/data networks: minecraft-net: ipv4_address: 172.30.0.10 restart: unless-stopped
twingate-connector: image: twingate/connector:1 container_name: twingate-connector environment: - TWINGATE_NETWORK=<YOUR_TWINGATE_NETWORK> - TWINGATE_ACCESS_TOKEN=<YOUR_ACCESS_TOKEN> - TWINGATE_REFRESH_TOKEN=<YOUR_REFRESH_TOKEN> networks: - minecraft-net restart: unless-stopped
networks: minecraft-net: ipam: config: - subnet: 172.30.0.0/24- Replace the placeholder values:
CF_PAGE_URLwith your modpack’s URL,CF_API_KEYwith your CurseForge API key, and the three Twingate values from Step 1.
Escape the dollar signs in your CurseForge API key
CurseForge API keys are bcrypt strings that start with $2a$10$. Docker Compose treats $ as the start of a variable reference, so pasting the key unmodified silently corrupts it. The server then fails with a misleading Access to https://api.curseforge.com is forbidden or rate-limit has been exceeded error, even though the key is valid.
Escape every $ in the key as $$ in docker-compose.yml. For example, a key of $2a$10$AbCdEf... is entered as:
CF_API_KEY: "$$2a$$10$$AbCdEf..."The image will confirm the key is read correctly when it begins downloading the modpack.
EULA
By setting EULA: "TRUE", you agree to the Minecraft End User License Agreement. Review it before proceeding.
Option B: Manual Mods
If you want to pick individual mods instead of using a modpack:
- Open a terminal on the machine.
- Create a project directory and navigate into it:
# macOS / Linuxmkdir -p ~/minecraft-forge && cd ~/minecraft-forge
# Windows (PowerShell)New-Item -ItemType Directory -Force ~\minecraft-forge; cd ~\minecraft-forge- Create a file named
docker-compose.yml:
services: minecraft: image: itzg/minecraft-server:latest container_name: forge-server environment: EULA: "TRUE" TYPE: "FORGE" VERSION: "1.20.1" MEMORY: "4G" MAX_PLAYERS: "10" MOTD: "Private Modded Server" volumes: - ./data:/data networks: minecraft-net: ipv4_address: 172.30.0.10 restart: unless-stopped
twingate-connector: image: twingate/connector:1 container_name: twingate-connector environment: - TWINGATE_NETWORK=<YOUR_TWINGATE_NETWORK> - TWINGATE_ACCESS_TOKEN=<YOUR_ACCESS_TOKEN> - TWINGATE_REFRESH_TOKEN=<YOUR_REFRESH_TOKEN> networks: - minecraft-net restart: unless-stopped
networks: minecraft-net: ipam: config: - subnet: 172.30.0.0/24-
Replace the Twingate placeholder values with your tokens from Step 1. Set
VERSIONto the Minecraft version your mods require. -
Start the server once to generate the data directory, then stop it:
docker compose up -d && sleep 30 && docker compose down- Copy your mod
.jarfiles into themodsdirectory. The first startup may not have createdmodsyet, so create it first:
mkdir -p ./data/modscp /path/to/your/mods/*.jar ./data/mods/Version matching
Every mod must be compatible with both your Minecraft version (VERSION) and your Forge version. Mixing versions is the most common cause of startup crashes.
Start the Server
How the private network works
Both containers share the minecraft-net bridge network. The server is pinned to 172.30.0.10 and no host port is published. The Connector reaches the server directly over the bridge at that address. This setup works identically on Linux, macOS, and Windows. (By contrast, network_mode: host only works on native Linux and breaks on Docker Desktop for macOS and Windows.)
- Start the containers:
docker compose up -d- Watch the logs:
docker compose logs minecraft -fForge servers take longer to start than vanilla. On first launch, expect 2-5 minutes while it downloads Forge, installs mods, and generates the world. Wait until you see a line containing For help, type "help" (the full line reads Done (15.0s)! For help, type "help"). Press Ctrl+C to exit.
If using a CurseForge modpack, the first startup also downloads all the mod files. On a slow connection this can take 10+ minutes. Subsequent starts are faster.
Verify the Connector
- In the Twingate Admin Console, navigate to Remote Networks and select your network.
- Click on the Connector. Verify that the Controller and Relay statuses both show Connected.
Step 3: Add the Forge Server as a Resource
The Resource configuration is the same as a vanilla server: TCP port 25565.
Server Address
The server is pinned to 172.30.0.10 on the minecraft-net bridge. No host IP address lookup is needed. That address is what you register as the Resource.
Create the Resource
- In the Twingate Admin Console, navigate to Resources and click Add Resource.
- Select the Remote Network from Step 1.
- Configure the Resource:
- Name:
Forge Server - Address:
172.30.0.10 - Protocols: TCP port
25565
- Name:
- Click Create Resource.
Assign Access
- Select the Group that contains your players (the default Everyone Group works for getting started) and click Grant Access.
Step 4: Connect Players
Modded Minecraft has an extra step compared to vanilla: every player needs the same mods installed on their client. The server will refuse connections from clients with missing or mismatched mods.
Install the Twingate Client
Each player installs the Twingate Client:
- Windows / macOS: twingate.com/download
- Linux: Linux Client install guide
Then sign in with the Twingate Network address (e.g., yournetwork.twingate.com) and the account the server admin invited you with.
Install the Mods
Players need to install the same mods the server is running. There are two ways to do this:
If Using a CurseForge Modpack (Option A)
- Install a mod launcher: CurseForge App, Prism Launcher, or ATLauncher.
- Search for the same modpack the server is running.
- Install it. The launcher downloads Forge and all the mods automatically.
If Using Manual Mods (Option B)
- Download and run the Forge installer for the same Minecraft version the server is running.
- Select Install client and click OK.
- Copy the same mod
.jarfiles the server uses into your client’smods/folder (typically~/.minecraft/mods/or%appdata%\.minecraft\mods\). - In the Minecraft Launcher, select the Forge profile and launch.
Mods must match
If a player’s mod list doesn’t match the server’s, they’ll see a “Mod rejections” screen listing the differences. Both the mod files and their versions need to be identical.
Add the Server in Minecraft
- In the modded Minecraft instance, click Multiplayer, then Add Server.
- Enter
172.30.0.10as the server address. - Click Done, then select the server and click Join Server.
You're in!
Players connect to 172.30.0.10 through the Twingate Client, with no port forwarding. The modded server stays off the public internet.
Step 5: Manage Player Access
Access management works the same way as a vanilla server. Create a Twingate Group, add your players, and assign the Group to the Forge Server Resource. See Step 5 in the vanilla guide for the full walkthrough.
Customizing the Server
CurseForge Modpack Options
| Variable | Description |
|---|---|
CF_PAGE_URL | Full URL of the CurseForge modpack page |
CF_SLUG | Alternative to CF_PAGE_URL: the modpack’s slug (e.g., all-the-mods-10) |
CF_API_KEY | Your CurseForge API key (required) |
CF_FILE_ID | Pin a specific modpack version instead of using the latest |
General Forge Options
| Variable | Default | Description |
|---|---|---|
TYPE | (required) | AUTO_CURSEFORGE for modpacks, FORGE for manual |
VERSION | LATEST | Minecraft version (pin this to match your mods, e.g., 1.20.1) |
FORGE_VERSION | (auto) | Specific Forge build (usually auto-detected from VERSION) |
MEMORY | 1G | Java heap size. Set to 4G-8G for modded servers |
MAX_PLAYERS | 20 | Maximum concurrent players |
MOTD | (none) | Message shown in the server browser |
OPS | (none) | Comma-separated player usernames to grant operator status |
After making changes, restart the containers:
docker compose down && docker compose up -dFor the full list of Forge and CurseForge options, see the itzg/minecraft-server Forge documentation.
Troubleshooting
“Mod Rejections” When Connecting
The server lists which mods are missing or have wrong versions. Compare the server’s mod list (./data/mods/) with the player’s client mods/ folder. Both sides need the same files.
If using a CurseForge modpack, make sure the player installed the same modpack version. Check the modpack version number in the launcher.
Server Crashes on Startup
- Check the logs:
docker compose logs minecraft. The most useful file is./data/logs/latest.log. - Look for
java.lang.OutOfMemoryError. If you see it, increase theMEMORYenvironment variable. Large modpacks need 6-8 GB. - Look for mod conflict errors. Two mods that modify the same game mechanic can crash the server. Try removing the most recently added mod and restarting.
- If using
AUTO_CURSEFORGE, check thatCF_PAGE_URLpoints to a valid modpack andCF_API_KEYis correct.
Server Takes a Long Time to Start
This is normal. Forge loads every mod at startup, and large modpacks (200+ mods) can take 3-5 minutes. First-time startup with AUTO_CURSEFORGE is even slower because it downloads all the mod files first.
If it takes more than 10 minutes, check the logs for errors. A mod that hangs during initialization will stall the whole startup.
CurseForge Download Failures
- Is
CF_API_KEYset? The CurseForge API requires a key for all downloads. - Is the key valid? Go to console.curseforge.com and verify your key is active.
- Some mods are marked “not allowed for third-party distribution” on CurseForge. The image will log which mods it couldn’t download. You’ll need to download those manually and place them in
./data/mods/.
Connector Shows Offline in Admin Console
- Are the
TWINGATE_NETWORK,TWINGATE_ACCESS_TOKEN, andTWINGATE_REFRESH_TOKENvalues correct indocker-compose.yml? - Does the host machine have outbound internet access? The Connector needs to reach Twingate Cloud.
- Check the Connector logs for errors:
docker compose logs twingate-connector.
Next Steps
- Vanilla Minecraft guide: Running an unmodded server alongside your Forge server.
- Bedrock Edition guide: Hosting Bedrock for mobile and Windows players.
- Resources: Learn more about configuring Twingate Resources, including wildcard DNS and CIDR-based Resources.
- Security Policies: Add multi-factor authentication or device trust requirements for players connecting to your server.
- Protect Your Home Lab: Extend Twingate to secure other services running on your home network.
Have questions or want to share your setup? Join us on the community subreddit.
Last updated 6 days ago