Mindustry Server 160.7 on AWS User Guide
Overview
This guide covers launching and using the Mindustry Server 160.7 on Ubuntu 24.04 AMI from cloudimg on Amazon EC2. It is one version of the cloudimg game server listing on AWS Marketplace; you pick it as the software version when you subscribe and launch.
Mindustry is an open source factory building tower defence game. Players mine resources, lay conveyor and power networks, automate production and defend what they have built against waves of enemies. It is at its best in multiplayer, where a group builds one factory together on a shared, persistent map, and that is what a dedicated server is for.
This image ships the dedicated server, not the game client. Each Mindustry release publishes several files and only server-release.jar is a server; Mindustry.jar is the desktop client. The build checks that the installed file really is the server (it carries mindustry/server/ServerLauncher.class, its manifest Main-Class is mindustry.server.ServerLauncher, and it carries no desktop client classes) before the image is captured. Your players install Mindustry normally on their own computers and use Join Game, Add Server with this instance's address.
The cloudimg image adds:
- A closed administration console. Upstream's remote console (
socketInput) has no authentication at all: anyone who reaches it can grant admin, ban players and stop the server. This image leaves it off, and the server refuses to start if it is ever switched on. Administration goes through a cloudimg console bridge bound only to127.0.0.1:6859that forwards nothing without this instance's console token, driven by the root onlymindustryctlcommand. - A token unique to your instance. First boot generates the console token on your instance. No token, world, save, admin list or ban list is baked into the image, and a committed secret guard refuses to start the server if the token is missing or weak.
- A contained service. The server runs as the
mindustrysystem account (no shell, no password) under a sandboxed systemd unit. The jar is owned by root, so the service cannot change its own code. - Loopback only outbound connections. A Mindustry server does not need to reach the internet: players connect in. A firewall rule keyed to the
mindustryaccount lets it open new connections only to the instance itself, on IPv4 and IPv6, so a map script, plugin or mod running inside the server cannot reach the instance metadata service, your VPC or the internet. Replies to players are not affected. The server units are also denied the metadata and link local addresses by systemd, and the AMI requires IMDSv2. - Anti-abuse defaults. A player limit of 30, chat rate limiting, strict mode, spam kicks and modified client rejection are configured instead of upstream's defaults, several of which are off.
- Saves that persist. Autosave every five minutes keeping the five most recent (upstream ships autosave off), and a reboot resumes the most recent autosave by itself.
- A self audit you can run.
mindustry-roundtrip-check.shproves the console refuses a wrong token, that a real Mindustry protocol client can join, that malformed clients are refused and that the world survives a full restart. - Exactly the ports players need. TCP and UDP 6567 for players and TCP 22 for SSH.
- A pinned, checked download. The unmodified upstream
server-release.jarfrom the v160.7 release, verified against a recorded sha256. - Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.
What is on the image: Mindustry server 160.7 (/opt/mindustry/server-release.jar), OpenJDK 21 runtime (Ubuntu package, no compiler), Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent.
Default user: ubuntu · Architecture: x86_64 · Recommended instance type: m5.large
Prerequisites
- An AWS account subscribed to the listing, an EC2 key pair and a VPC subnet with a route to the internet.
- A public IPv4 address on the instance (auto assigned or an Elastic IP), so players on the internet can reach it.
- A security group that allows TCP 6567 and UDP 6567 from your players (usually anywhere) and TCP 22 (SSH) from your own networks only. Mindustry needs both protocols on 6567.
- Your players need the Mindustry game at the same version, 160.7.
Do not open port 6859. That is the administration console; it is bound to loopback and reached over SSH.
Step 1: Launch the instance
In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick Mindustry Server 160.7 on Ubuntu 24.04 as the software version and your Region, then Launch through EC2. Choose m5.large, your key pair and a security group as above. The server itself is modest: it used about 162 MB of memory with a world hosted and a player connected, and the Java heap is capped at 1024 MB.
With the AWS CLI (replace the values in angle brackets):
aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
--instance-type m5.large --key-name <your-key-pair> \
--security-group-ids <your-security-group> --subnet-id <your-subnet> \
--associate-public-ip-address \
--metadata-options HttpTokens=required,HttpEndpoint=enabled \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=mindustry}]'
The security group rules, from the AWS CLI:
aws ec2 authorize-security-group-ingress --group-id <your-security-group> \
--ip-permissions 'IpProtocol=tcp,FromPort=6567,ToPort=6567,IpRanges=[{CidrIp=0.0.0.0/0}]' \
'IpProtocol=udp,FromPort=6567,ToPort=6567,IpRanges=[{CidrIp=0.0.0.0/0}]' \
'IpProtocol=tcp,FromPort=22,ToPort=22,IpRanges=[{CidrIp=<your-mgmt-cidr>}]'
Step 2: Connect to your instance
| Version | SSH user |
|---|---|
| Mindustry Server 160.7 on Ubuntu 24.04 | ubuntu |
ssh -i <your-key.pem> ubuntu@<public-ip>
Step 3: Check first boot and read your credentials
On first boot the instance generates its own console token, prepares a clean state directory, starts the server, applies the shipped configuration, hosts the Ancient_Caldera map and then proves a real Mindustry protocol client can join before it declares itself ready. Give it two or three minutes after the instance reports running, then check it:
systemctl is-active mindustry-firstboot.service mindustry.service mindustry-console.service cloudimg-mindustry-egress.service
All four should report active. Then read this instance's credentials:
sudo cat /root/mindustry-credentials.txt
The file is 0600 root:root and was written on your instance. It holds the console token, the instance's addresses (read with IMDSv2) and the address players connect to:
MINDUSTRY_CONSOLE_TOKEN=<console-token>
MINDUSTRY_CONSOLE_ENDPOINT=127.0.0.1:6859
MINDUSTRY_PRIVATE_IP=<private-ip>
MINDUSTRY_PUBLIC_IP=<server-ip>
MINDUSTRY_GAME_ADDRESS=<server-ip>:6567
MINDUSTRY_VERSION=160.7
Keep the token as you would any other secret. It is not a player password: Mindustry has no player login, and the game port is meant to be public. If the instance has no public IPv4, the public and game addresses show the private address, which only works inside your VPC or VPN.
Then check the server is hosting a world:
sudo mindustryctl status
You should see the map being played, the wave, the time until the next wave and the connected players. If it says server closed, no world is hosted; see Step 6.
Step 4: Connect from the game
- Open Mindustry on your own computer (Steam, itch.io or the official build) at version 160.7.
- Choose Play, Join Game, Add Server.
- Enter
MINDUSTRY_GAME_ADDRESSfrom the credentials file: the public IP with:6567. - The server appears with its name, map and player count. Select it to join.
The server refuses clients on a different build, by design, so worlds do not desynchronise. It also refuses modified clients, because allowCustomClients is false in this image.
Step 5: Administer the server
mindustryctl drives the server's own console through the token checked bridge. It is root only (0750 root:root):
sudo mindustryctl help
Everyday commands:
sudo mindustryctl status # what is hosted, wave, players
sudo mindustryctl players # who is connected, with their IDs
sudo mindustryctl maps all # the built in maps you can host
sudo mindustryctl playerlimit # the current player cap
Admins are granted by player ID, shown by players while the player is connected. Take the value after ID: and run the following (the player should reconnect afterwards to pick up the new status; admin remove <id> reverses it):
sudo mindustryctl admin add <their-player-id>
sudo mindustryctl admins
To deal with a griefer:
sudo mindustryctl kick <player-name>
sudo mindustryctl ban id <their-player-id>
sudo mindustryctl unban <id-or-ip>
sudo mindustryctl bans
Vote kick is on, so your players can remove a griefer themselves, and strict mode corrects positions and rejects duplicate player IDs.
A wrong token is refused with a fixed one second delay and deliberately no lockout, so a typo never locks you out of your own server.
Step 6: Host a map
The game port only exists while a world is hosted: Mindustry opens the listener when you host and closes it when you stop.
sudo mindustryctl maps all
sudo mindustryctl host Ancient_Caldera survival
Loading a large map can take a minute or two. Then confirm it with sudo mindustryctl status. Other modes are attack, pvp, sandbox and editor. To end the current world run sudo mindustryctl stop and host another; to start the next wave now run sudo mindustryctl runwave.
Step 7: Saves, restarts and logs
- Autosave is on every 300 seconds and keeps the five most recent, so saves cannot fill the disk.
- A reboot resumes the most recent autosave, and hosts the default map if there is nothing to resume.
- Named saves are yours to make and keep:
sudo mindustryctl save my-world
sudo mindustryctl saves
Saves live in /var/lib/mindustry/config/saves as .msav files. Copy them off the instance with scp for a backup you control, and bring one back with sudo mindustryctl load my-world. To resume the latest autosave by hand, run sudo mindustryctl loadautosave.
The server log is /var/log/mindustry/mindustry.log, rotated daily or at 32 MB and keeping seven compressed generations for at most 30 days:
sudo tail -20 /var/log/mindustry/mindustry.log
mindustryctl strips Mindustry's colour codes; the raw log keeps them, which less -R renders.
Step 8: Tune the server
Configuration is the plain text file /etc/mindustry/server-commands.conf, which the service replays into the server console on every start. Mindustry's own settings.bin is a binary file that also holds the admin list, ban list and player database, so the image ships none and configuration stays readable as text.
sudo cat /etc/mindustry/server-commands.conf
| Setting | This image | Upstream default |
|---|---|---|
playerlimit |
30 | no limit |
messageRateLimit |
2 seconds | 0 (chat rate limiting off) |
messageSpamKick |
3 | 3 |
allowCustomClients |
false |
true on desktop builds |
autosave |
true, 5 kept |
false |
socketInput |
false |
false (and unauthenticated when on) |
To change a setting, edit the file and restart:
sudoedit /etc/mindustry/server-commands.conf
sudo systemctl restart mindustry.service
A setting changed live with sudo mindustryctl config <name> <value> reverts to the file on the next restart. For an invite only server, add config whitelist true to the file, have each player connect once, then run sudo mindustryctl whitelist add <their-player-id>.
The Java heap is capped at 1024 MB in /usr/local/sbin/mindustry-run.sh. If a very large map with many players needs more, raise -Xmx there and move to a larger instance type.
Step 9: Security checks
Only SSH (TCP 22) and the game port (TCP and UDP 6567) listen on the network. The console bridge listens on loopback only:
sudo ss -H -tulnp | grep -E ':(22|6567|6859) '
The administration console answers only on 127.0.0.1:6859, and the kernel only lets root open a connection to it. The server account can open new connections only to the instance itself. Both rules are loaded by cloudimg-mindustry-egress.service before the server starts, and the server refuses to start without them. To see them:
sudo mindustry-egress-apply --print
The server units are also denied the instance metadata service and link local addresses:
systemctl show mindustry.service -p User -p NoNewPrivileges -p PrivateTmp -p IPAddressDeny
Java's temporary directory is private to the service (/var/lib/mindustry/.tmp, mode 0700), and the console token is never written to the logs or the journal.
ubuntu and root keep normal access to the instance metadata service with IMDSv2, so the AWS CLI and the SSM agent work as usual.
If you add a plugin or mod that needs to reach the internet (for example a chat bridge), the outbound rule refuses it. That is deliberate: run such integrations as their own service under a different account rather than loosening the game server.
Step 10: Verify your deployment
The image carries its own audit. It takes a few minutes because it really restarts the server and reconnects a client:
sudo /usr/local/sbin/mindustry-roundtrip-check.sh
It proves, in order:
- the console token is required, and a wrong or empty one executes nothing (the real one is proven again straight after, so the refusal is not a lockout);
- the console answers on loopback and not on the instance's private address, while the game port on that same address does;
- a real Mindustry protocol client completes the handshake and the server lists the connected player;
- malformed clients (wrong build, wrong client type, empty name) are refused;
- the world survives a full service restart with the same map and wave;
- logrotate really rotates.
It ends with MINDUSTRY_ROUNDTRIP_OK and exits non-zero if anything failed.
Step 11: Server components
| Component | Version | Location |
|---|---|---|
| Mindustry server | 160.7 (unmodified upstream server-release.jar) |
/opt/mindustry/server-release.jar (root owned) |
| OpenJDK | 21 runtime (Ubuntu package, security updates via unattended upgrades) | /usr/lib/jvm |
| State, saves and maps | /var/lib/mindustry/ |
|
| Configuration | /etc/mindustry/server-commands.conf |
|
| Console token | /etc/mindustry/console.token (0640 root:mindustry) |
|
| Log | /var/log/mindustry/mindustry.log |
|
| Admin command | /usr/local/sbin/mindustryctl |
|
| Self audit | /usr/local/sbin/mindustry-roundtrip-check.sh |
|
| First boot | mindustry-firstboot.service, credentials in /root/mindustry-credentials.txt |
|
| Licence and source offer | /usr/share/doc/mindustry/ |
Step 12: Security recommendations
- Allow TCP 22 only from your own networks; only TCP and UDP 6567 need to be open to players.
- Never open 6859 and never switch
socketInputon. The server refuses to start with it on. - Keep
/root/mindustry-credentials.txtand/etc/mindustry/console.tokenprivate. - Use the whitelist (Step 8) if the server is for a known group of players.
- Copy saves off the instance regularly (Step 7).
- Unattended upgrades keep Ubuntu and OpenJDK patched; update Mindustry when your players move to a new release.
Troubleshooting
- Players cannot find or join the server. Check a world is hosted:
sudo mindustryctl statusmust not sayserver closed. Then check the security group allows TCP and UDP 6567; opening only TCP is the most common cause of "it shows up but will not connect". - A player is refused. Almost always a version mismatch: the client must be on 160.7. Modified clients are refused by design.
sudo tail -20 /var/log/mindustry/mindustry.logshows the reason. mindustryctlsays the console is unreachable. Check the units withsystemctl is-active mindustry.service mindustry-console.service cloudimg-mindustry-egress.service. If the server is not active, runsudo /usr/local/sbin/mindustry-secret-guard.sh: it explains why it refused to start (a missing or weak token,socketInputswitched on, or the outbound rule not loaded).- The world is gone after a restart. Run
sudo mindustryctl loadautosave, or load a named save.
Support and licensing
cloudimg provides 24/7 technical support for this image by email and live chat at support@cloudimg.co.uk. Include the output of sudo /usr/local/sbin/mindustry-roundtrip-check.sh and the last lines of /var/log/mindustry/mindustry.log with a request. For gameplay, mods and map making, the Mindustry project and its community are the right place.
Mindustry is free software under the GNU General Public License, version 3, and cloudimg does not modify it. The server jar also contains the Arc framework (Apache-2.0), a fork of Mozilla Rhino (MPL-2.0), lz4-java (Apache-2.0, with the LZ4 C library under BSD-2-Clause) and JLine (BSD-3-Clause), and it runs on OpenJDK 21 (GPL-2.0 with the Classpath Exception). The image ships the GPL text and a written offer for the corresponding source:
ls /usr/share/doc/mindustry/ && head -12 /usr/share/doc/mindustry/SOURCE.txt
SOURCE.txt names the exact upstream tag and the sha256 of the installed jar, and links to the source tree at that tag. cloudimg's own additions (the console bridge, first boot, the protocol probe and the audit scripts) are separate files under /usr/local, also GPL-3.0-or-later, and the protocol probe's source ships next to its compiled classes.
Mindustry is a trademark of its authors. cloudimg is not affiliated with or endorsed by the Mindustry project.