Your VPS. Your game servers. Your worlds.
Playkeeper is a self-hosted dashboard for running Minecraft Java servers on a Linux VPS you already own, or on several machines: install it, create servers in the browser, add plugins, mods and modpacks, browse and edit each server's files, invite friends and co-admins, see real player and server activity, and keep backups on the server and off it. It works on a phone as well as a desktop. To click around first, open the live demo: sample servers and players, running in your browser, nothing real, starting over every hour. Questions and ideas are welcome in GitHub Discussions.
Status: v0.4.2, an early release. Tested on every change on fresh GitHub-hosted Ubuntu 24.04 runners: install, onboarding, play with protocol-level test bots, backup, restore on a second runner, the upgrade from the current release and an update from the dashboard with the automatic rollback, certificates from Let's Encrypt's test CA, and every page at desktop and phone width with an accessibility check. Before every release, the same install, play, backup, restore, update and uninstall run on x86_64 on Ubuntu 20.04, 22.04, 24.04 and 26.04, Debian 12 and 13, AlmaLinux and Rocky Linux 9 and 10, Oracle Linux 9, CentOS Stream 9 and Amazon Linux 2023, each in a fresh copy of its official cloud image, and the install, play, backup, restore and uninstall, with every server type, on 64-bit ARM on GitHub-hosted Ubuntu 24.04 ARM runners. Verified by the owner: installing on a real provider VPS, and playing there with friends on 0.3.1. Not yet tested: RHEL itself and CentOS Stream 10; on ARM, any system but Ubuntu 24.04, the RHEL family and Amazon Linux included; and ARM servers other than GitHub's runners, such as a Raspberry Pi or Oracle Cloud's Ampere A1. Not yet tried with the real services: a Discord channel, a free name from Playkeeper's names service, a Let's Encrypt certificate, a CurseForge modpack with the key built into the release, and copies to S3-compatible storage. Keep your own copies of any backup you care about.
On the VPS:
curl -fsSL https://playkeeper.io/install | sudo shNo sudo, as on a Debian installed with a root password? Run su -, then the same command without sudo.
https://playkeeper.io/install is a few lines that run get.sh from the latest release, telling it the install came through playkeeper.io. The script downloads the tarball for your VPS's CPU from that release, playkeeper-linux-amd64.tar.gz on x86_64 or playkeeper-linux-arm64.tar.gz on 64-bit ARM, and its .sha256, stops unless the SHA-256 matches, then runs the installer, which asks before changing anything. Installer options go after sh -s --, for example … | sudo sh -s -- --yes --game-port 25566. To read what runs first: curl -fsSL https://playkeeper.io/install, then get.sh at the address it names. The installer first says that it sends anonymous usage stats; curl -fsSL https://playkeeper.io/install | sudo DO_NOT_TRACK=1 sh installs without them.
If playkeeper.io is unreachable, the same script comes straight from GitHub:
curl -fsSL https://github.com/CIYAhq/playkeeper/releases/latest/download/get.sh | sudo shTo skip the script, download the tarball for the VPS's CPU and its .sha256 from the releases page to the VPS: playkeeper-linux-amd64.tar.gz if uname -m says x86_64, playkeeper-linux-arm64.tar.gz if it says aarch64. Then:
ARCH=amd64 # arm64 on a 64-bit ARM VPS
sha256sum -c playkeeper-linux-$ARCH.tar.gz.sha256 && tar -xzf playkeeper-linux-$ARCH.tar.gz
sudo ./playkeeper-*-linux-$ARCH/install.shHow big a VPS? The sizing guide answers for how many friends play at once and what you'll run.
Runs on: Ubuntu 20.04 or later, Debian 12 or later, the RHEL family 9 or later (AlmaLinux, Rocky Linux, Oracle Linux, RHEL and CentOS Stream), or Amazon Linux 2023 or later, on x86_64 or 64-bit ARM with systemd. Before every release it is installed, played on, backed up, restored, updated and uninstalled on Ubuntu 20.04, 22.04, 24.04 and 26.04 LTS, Debian 12 and 13, AlmaLinux and Rocky Linux 9 and 10, Oracle Linux 9, CentOS Stream 9 and Amazon Linux 2023, each in a fresh x86_64 KVM guest built from its official cloud image (3 GB RAM, 2 vCPU, 20 GB disk), with SELinux enforcing where the image enforces it. RHEL itself and CentOS Stream 10 aren't booted there: AlmaLinux and Rocky Linux rebuild RHEL's packages, and CentOS Stream 10 is where RHEL 10 is developed. Every change also runs on GitHub-hosted ubuntu-24.04 runners, and the owner has installed it on a real provider VPS (see the status above). On 64-bit ARM, before each release, it runs on Ubuntu 24.04 LTS on GitHub-hosted ubuntu-24.04-arm runners: install, onboarding, play with test bots, backup, restore on a second runner, every server type with the hand-picked add-ons, the map, pre-generation and a modpack, and uninstall. The other systems haven't been tried on ARM yet, nor have the ARM servers the arm64 build is for, such as Oracle Cloud's free Ampere A1, Hetzner's and AWS's (Graviton) ARM machines and a Raspberry Pi 4 or 5 with a 64-bit OS. A newer release of a supported distribution than these gets a warning, not a refusal. Ubuntu 20.04 still works, but its standard security updates ended in May 2025 (Ubuntu Pro has more), and the installer says so. Debian 11 isn't supported: since its long-term support ended in August 2026, Debian's archive no longer has the Docker packages its package lists point to, so Docker can't be installed from it. The installer refuses a 32-bit system on a 64-bit CPU, and other distributions and older releases need --allow-untested-os.
You need: root (sudo) on the VPS; an x86_64 or 64-bit ARM CPU with a 64-bit OS; at least 2 vCPUs (the size that was tested; the installer does not check the count); at least 3 GB RAM (2.3 GB is the hard minimum the installer accepts) and 5 GB free disk (3 GB minimum). Open these in your provider's firewall (the installer opens them in ufw or firewalld itself when one is on, as on Oracle Cloud's images):
- TCP 8443 for the dashboard;
- TCP 443 for the dashboard without a port once the VPS has a name (below), and for your servers' public page;
- TCP 25565 for the first Minecraft server, plus one more from 25566 for each further server;
- UDP 24454 (or the next free port) for each server with voice chat;
- UDP 19132 (or the next free port) for each server with crossplay, for Bedrock players;
- TCP 80 to send browsers on to port 443, and if you give the dashboard your own domain, for Let's Encrypt's checks while it issues or renews the certificate.
playkeeper.io/ports has the steps for AWS, Google Cloud, Azure, Oracle Cloud, DigitalOcean, Hetzner, Vultr, Hostinger and Linode.
When ufw or firewalld is on, the installer allows 8443, 25565, 443 and 80 in it (in firewalld, in the zone of the network interface with the default route, saved and running). Another firewall on the server, such as nftables on Debian, needs its own rules: the installer's check says which one it found and how to allow the ports.
On Oracle Cloud, whose Ubuntu images let in only SSH, with iptables rules saved for iptables-persistent, the installer allows the ports there too, right before the rule that rejects everything else, running and in /etc/iptables/rules.v4; uninstall takes them out. Older Playkeeper versions need them allowed by hand (Troubleshooting).
Outbound, Playkeeper needs your system's package repositories if it installs Docker (and Docker's, download.docker.com, on the RHEL family), and HTTPS to GitHub, Docker Hub, PaperMC and Mojang and, for the features you use, to Modrinth and Hangar (plugins, mods and modpacks; a Modrinth modpack may also fetch files from GitHub or GitLab), GeyserMC (crossplay's Floodgate), CurseForge, the download sites of Purpur, Fabric, Quilt, NeoForge and Forge, the websites a template's data packs come from, Discord, Let's Encrypt with Playkeeper's names service or public DNS-over-HTTPS (addresses), your own storage (off-site copies), and the project's stats service, for usage stats and the Overview's check from the internet, which has it connect back to a server's port. On a machine with only a private address, behind its provider's NAT as on AWS, Google Cloud, Azure and Oracle Cloud, the installer also asks the names service once which address its requests come from, so the dashboard link it prints has the public one. If Docker is missing, the installer installs Ubuntu's or Debian's docker.io package (with docker-cli on Debian 13, which packages the docker command on its own), Amazon Linux's docker package, or on AlmaLinux, Rocky Linux, Oracle Linux, RHEL and CentOS Stream Docker Engine (docker-ce) from Docker's repository, checked with Docker's signing key, which the installer carries. An existing Docker is used as it is; Podman can stay alongside, and the installer never removes it or what it needs. To check a server without changing it, extract the tarball as above and run sudo ./playkeeper-*-linux-$ARCH/playkeeper preflight.
The installer checks the server first (changing nothing), lists every change it will make and how to undo it, and asks before continuing. It never takes over an existing Minecraft, Crafty or panel install: it installs next to old ones that don't run or start again by themselves, and leaves them alone, and stops at ones that do, with the one thing to do. When it finishes it prints:
- an
https://<your-ip>:8443/setup#code=…link with a one-time setup code (24 hours), and - what to do about the browser's warning. The dashboard starts with a self-signed certificate, so the browser says the connection isn't private: click Advanced, then Proceed (in Safari, Show Details, then visit this website). The installer's last line gives the certificate's SHA-256 fingerprint, for anyone who wants to compare it with the one the browser shows. A name with a real certificate (below) makes the warning go away, and the dashboard then opens at the name without a port, like
https://alex.playkeeper.me.
Everything else happens in the browser: create the admin account, pass the check of the VPS, then create your first server or skip it for now. The first server gets the newest stable Paper and a memory size for how you'll play; Change picks others. The Get started card in the sidebar and First steps on each server's Overview walk you through inviting a friend and making and downloading your first backup.
New server walks through the type, version, play style, memory and name, with the recommended version and a memory size already picked. Start from can also begin with a modpack, a template or a world you already have. Each server has its own world, players, backups, settings, game port and share of the machine's memory.
- Server types: Paper, Purpur, Vanilla, Fabric, Quilt, NeoForge and Forge, for Minecraft 1.20.1 and newer, each downloaded from its own project and checked against the checksum it publishes. Each server runs on the Java its Minecraft version was made for: Java 17 for 1.20.1, 21 for 1.21 and 25 for 26.1 and newer.
- Modpacks: browse Modrinth, and CurseForge through the key built into the release or your own free key (Settings › Add-on sources; the key stays on the machine, and only the owner can change it there), for Minecraft 1.20.1 and newer, like All the Mods 9 and Better MC 4. See what's inside, then create the server, with each file checked as it downloads.
- Templates: Share as a template in a server's menu makes a
.playkeeper-templatefile or ahttps://playkeeper.io/t#…link with its type, version, settings, add-ons and modpack (from Modrinth or CurseForge): names, versions and checksums only, never files, worlds, players or secrets. Anyone with their own Playkeeper can create a server from it. - Your own world: Start from › A world, or Start from your own world on a server's World tab, takes your singleplayer world or one from Aternos, Minehut, Realms or another host (with steps for getting it out), as up to 16
.zip,.tar.gzor.tarfiles. The upload carries on where it stopped if the connection drops. Before anything changes, Playkeeper shows what's inside and which Minecraft version will run it; a world that gets upgraded keeps the file you uploaded as a backup. - Minecraft version: Minecraft version in a server's Settings offers newer versions. Back up and update takes a backup first and puts it back if the server doesn't start. A world opened with a newer version can't go back.
- Plugins and mods: the Plugins tab (Mods on Fabric, Quilt, NeoForge and Forge; Vanilla has neither) searches Modrinth, and for plugins Hangar too, in one list of what works on the server's type and version, starting with a few add-ons Picked by Playkeeper. Installing shows what will be added, dependencies included, and checks every file against the checksum its library publishes. Update one or all, remove with or without settings, and take over plugins you added by hand so they get updates too. New and updated plugins load when the server restarts.
- Voice chat: installing Simple Voice Chat opens its UDP port (24454, or the next free one) on that server and closes it when you remove it. A template that has it opens the port too; a modpack that brings it opens the port only if you choose Create and open the port. Open the port in your provider's firewall too; the dialog gives you the link friends need for the mod.
- Crossplay: Bedrock players in a Paper or Purpur server's Settings lets friends on Minecraft: Bedrock Edition join: phones, tablets and Windows add the server themselves, and Xbox, PlayStation and Switch need a workaround such as BedrockConnect. It installs Geyser from Modrinth and Floodgate from Hangar (Floodgate's file comes from GeyserMC's download server, which its listing links to, checked against the SHA-256 GeyserMC publishes), opens UDP 19132 (or the next free port) and restarts the server. Bedrock friends type the machine's address and that port, which the server's Join card shows: Bedrock doesn't use the servers' own addresses. Their names on the server start with a dot, so add them to the allowlist on the Players tab as
.then their Xbox gamertag. Geyser and Floodgate update on the Plugins tab like other plugins; update Geyser when Bedrock updates. Backups keep the port, and turning crossplay off removes both plugins and closes it. Open the port in your provider's firewall too. A template doesn't carry crossplay. - Friends on a modded server: Share with friends on the Mods tab makes one link to a page that shows friends what to install, with a
.mrpackfile for the Modrinth App or Prism Launcher. It shows names and versions only, and server-only mods stay hidden. The link is random and changes when you stop and start sharing. - Pre-generate the map: on the World tab (every server type but Vanilla), builds the land out to 1,000, 2,500, 5,000 or 10,000 blocks from spawn ahead of time, so exploring doesn't lag. Each size shows how long it takes and how much disk it needs. It installs Chunky the first time, pauses while people play unless you turn that off, and can be paused, resumed or cancelled.
- Resource and data packs: on the World tab,
.zipfiles up to 250 MB. A data pack goes into the world; a resource pack is offered to every player when they join, optionally required and with your message. Players' games download it from the dashboard's address and port, over HTTPS once the dashboard has a Let's Encrypt certificate for that address and over plain HTTP until then, so add it with the dashboard open at the address players join with. - Files: the Files tab (for admins) shows a server's folder: open
server.properties, YAML, JSON, TOML and other settings files in an editor that marks what Playkeeper sets from Settings, upload files or whole folders by dragging them in (an upload carries on where it stopped if the connection drops), download files or folders as a zip, and make folders, rename, move and delete. Other files are download-only. While the server runs its world is read-only, and other changes apply when it restarts. - Map: the Map tab (every server type but Vanilla and Forge) shows the world from above, drawn by squaremap on your own server, with who's playing and where. Turn on the map installs squaremap, which loads with one restart. Share with a link gives a link that works without signing in; each new link retires the old one, and player positions stay hidden unless you turn on Show players on the shared map. Map area, in the map's … menu, shows the explored land, or a bigger area around spawn or up to the world border, which Playkeeper pre-generates first (as above) while the map draws it.
- Backups: Back up now on the World tab copies the world while players stay online: Playkeeper pauses saving only while it copies, then checks the copy file by file. If a plugin keeps writing to the world, Stop and back up makes the backup with the server stopped instead.
- Backup rules: World › Backup rules makes backups by themselves, every few hours or once a day, if you like only when someone played, and keeps every backup from the last hours, then one a day, a week and a month. By default that is everything from the last 24 hours, one a day for 7 days and one a week for 4 weeks. The page shows about how many backups that keeps and how much space they take.
- Copies somewhere else: every backup can also go to S3-compatible storage (Backblaze B2, Cloudflare R2, Wasabi and similar) or to another machine over SFTP, encrypted on your server first. Download the recovery key when you turn copies on and keep it off the server: on a new machine, Restore from a recovery key on Home finds a server's copies and restores one as a new server.
- Schedules: Schedules in a server's Settings runs restarts that warn players first, backups and a short list of safe console commands, every day, on chosen days or every few hours, in your time zone. A restart or backup can skip while people play and try again an hour later. Schedules keep running while the dashboard is down.
- Sleep when nobody's playing: off until you turn it on in a server's Settings. While another job runs on that server, such as a backup, changing it is refused as busy; save it again once the job is done. After 5 minutes to 4 hours with nobody on (15 minutes by default), the server stops and frees its memory, and players see "Asleep · join to wake it". Joining wakes it in about 30 seconds: a banned player never wakes it; with the allowlist off anyone else can, and with it on only players on the allowlist and operators can. You can also wake it from the dashboard.
- When something's wrong: How it's running, under a server's Overview, shows the tick rate, tick time, memory and processor use, and what slows the server down, each with one thing to do. When a server crashes or doesn't start, its Overview explains why from its own log and crash report and offers the fix. Memory in a server's Settings suggests a size from the last 14 days.
- Disk space: the machine's Disk meter opens a page showing what fills the disk and what each server uses, with ways to free space: old backups, logs and crash reports, unused server versions, downloaded add-on files, folders set aside by restores and updates, and unfinished files. Nothing is deleted until you press its button and confirm, old backups and set-aside folders are listed one by one so you pick what goes, and off-site copies stay.
- Invite friends: New invite link on a server's Players tab. A friend opens it, types their Minecraft name and is on the allowlist, right away or once you say yes. A link works for a day, a week, a month or until you turn it off, for a set number of friends, and the Players tab shows who joined with which link.
- Player pages: each player's page shows when and how long they play and whether they're on the allowlist or an operator, and lets you message, kick or ban them.
- Team: Settings › Team invites someone as an Admin, Moderator or Viewer, for every server or only some, with their own sign-in. Someone with only some servers sees only those servers and the team members who share one with them. Admins must use two-factor sign-in; until they turn it on and you confirm it with one click, they have Moderator rights.
- Discord: Settings › Discord takes a channel's webhook link for alerts (a crash, back online, low disk space, a failed backup, a new Playkeeper or Minecraft version, a join request or a player the allowlist turned away, and players joining and leaving in a server's first week, or always if you want them) and keeps one live status message with each server and who's playing. It covers the servers on the dashboard's machine; servers on connected machines don't post to Discord. Alerts come from that machine's agent, so a crash is reported even while the dashboard is down.
- Two-factor sign-in: Your account (your name at the bottom of the sidebar; on a phone, More › your name) › Turn on: enter your password, scan the QR code with an authenticator app, type its code and save the ten recovery codes. Five wrong codes in a row pause app codes for a minute, doubling up to 16 minutes; 100 block them until a recovery code is used. If you lose the phone and the codes, run
sudo playkeeper reset-2fa <username>on the VPS.
Machine settings › Address (on a phone: More › your machine › Address) gives the dashboard's machine a free yourname.playkeeper.me name or your own domain, and the dashboard a Let's Encrypt certificate that renews by itself. With your own domain, add the records Playkeeper lists where you manage the domain (an A record, and an SRV record for each server not on port 25565) and open port 80 for Let's Encrypt's checks; each server then joins at its own address, without a port. Under your own domain, Servers' own addresses can give a server an address of its own, like alex.example.com next to the machine's mc.example.com: add its A and SRV records, and players join it there without a port, a browser opening it gets that server's own public page, and Playkeeper gets its certificate, at most a few new ones a day. Or turn on An address for each server there and add one record, *.mc.example.com: every server then gets an address like survival.mc.example.com by itself, with its own page and certificate, and players type the server's port with it. A free name comes from Playkeeper's names service: three days after the claim, once the service has reached the dashboard on port 8443, the first five servers get their own address, and until then (and for any further servers) players add the server's port to the name. Servers on connected machines join at that machine's IP address and each server's port. The IP address and its self-signed certificate keep working. Invite, map and pack links use the name once there is one. Opening the name in a browser, without a port, shows a public page for your servers: their status, how to join and the shared map's link, with player names only if you show them (Settings › Public page on each server). There you can add your own words, like the server's rules, and a Twitch or YouTube channel that visitors can watch, and your tools can post a status board to it through the API or MCP: a headline, whether you're live and when the next session starts, a few numbers and a checklist. A link to the page shows a picture of the server where it's shared. It uses ports 443 and 80 only while nothing else on the VPS uses or claims them.
The dashboard without a port: with Serve the dashboard on the standard HTTPS port (443) on, in Machine settings below the address, the dashboard opens at https://yourname.playkeeper.me or your own domain instead of …:8443. A new install turns it on when nothing uses port 443; an update leaves it off until you turn it on, and it can't be turned on while another program, a Docker container or a web server set to start with the VPS has port 443, which it names. Allow TCP 443 in your provider's firewall first. The address loses its port once a browser from outside the VPS has opened it there, which Machine settings checks from your browser (or asks you to open it once), so a firewall that drops port 443 never leaves you with an address that doesn't open. Signed in, the name opens the dashboard; for anyone else it shows your servers' public page with Sign in, or the sign-in page where customers sign in with Whop. Port 8443 keeps answering: it sends browsers that open a page there to the address without a port, and keeps serving the API, /mcp, Whop's webhook, the free address check and connected machines, so old links, bookmarks and tools keep working. Invite, map and pack links, AI agents' address, Discord's links, Whop's webhook and the messages customers get use the address without a port. Machine settings lists what outside Playkeeper keeps the old one, with the change each needs: with Sign in with Whop, add the new redirect URL on the Whop app's OAuth tab, beside the old one, which customers come back through until you do. The panel still runs without the right to open ports below 1024: the agent opens port 443 and hands it over, as for the public page. Free names used to end in .playkeeper.io: an install from before the move gets the same name under .playkeeper.me when it updates, and the old address keeps reaching it for two months.
- Servers on more machines: Settings › Machines › Connect another machine makes a one-line command for a second VPS or a home server (any system Playkeeper runs on, with at least 2 CPU cores, 3 GB of memory and 5 GB of free disk). Its CPU needn't match the dashboard machine's: each machine, x86_64 or 64-bit ARM, installs and updates its own build. On a new machine it installs Playkeeper without a dashboard of its own; on one that already runs Playkeeper, it's
sudo playkeeper join …. The machine dials out to your dashboard's address and port and reconnects by itself, so no port opens on it for Playkeeper; its servers' game ports need opening there as usual. Its servers show up on Home and in the sidebar with the others. Each code works once, for 30 minutes, and the fingerprint in the command proves the machine found your dashboard. Open the dashboard at its IP address or domain name to get the command, and usesudo playkeeper leaveon the machine to disconnect it. - AI agents: Settings › AI agents shows the dashboard's MCP address and makes a token for each AI tool, such as Claude or Cursor, for 30, 60, 90 or 365 days and for all servers or some. A token has a Viewer's rights (status, players, the console and crashes, and searching for plugins and mods), a Moderator's (also start and stop, backups, the allowlist and the public page's status board) or an Admin's (also console commands, and installing and removing plugins and mods), and never more than your own account: it stops working if you're removed from the team, your role is lowered or you lose a server it's for. What agents do shows up there and in the activity log. Over SSH,
sudo playkeeper mcpserves the same tools with the owner's rights, for that machine's servers.
Update Playkeeper: when a new release is available, Playkeeper X is out appears at the bottom of the sidebar (at the top of Home on a phone) for the owner and admins of every server; Update shows what changed and installs it when you click Update again, and the close button hides the notice until the next release. Before anything from the download runs, Playkeeper checks that the release's manifest is signed with the Playkeeper release key built into your installed version, and that the download matches the manifest. Only the dashboard and agent restart; the Minecraft servers keep running. If the new version is not healthy within two minutes, the previous version, its services, settings and databases are put back automatically. From 0.4.9, Playkeeper looks for a new release when it starts and about every 30 minutes (earlier versions: a minute after it starts, then twice a day): one small request to playkeeper.io, answered "not modified" until a release comes out, with GitHub asked instead when playkeeper.io doesn't answer. It downloads nothing until you click, and never goes back to an older version. Settings › Playkeeper › Check for updates automatically turns the looking off; Check for updates still looks when you press it. Machines connected to your dashboard update from Settings › Machines.
Upgrade to 0.4.2: install it from the dashboard. A free name moves from .playkeeper.io to .playkeeper.me by itself (A name for your VPS). From a release before 0.4.0, a server on a Minecraft version before 26 also moves to the Java that version was made for, so its next start downloads that runtime once and takes longer.
Upgrade from 0.1.0: 0.1.0 cannot update itself. Run the same one-line install command on the VPS: it sees the installed version, shows what it keeps and replaces, and upgrades in place. Worlds, backups, settings and the admin account are kept, and later updates come from the dashboard. Running the command again later is safe: it does nothing if the version is the same and refuses an older one.
Uninstall: sudo playkeeper uninstall lists what it removes and asks first: Playkeeper, its services, users, containers and firewall rules, and the Docker packages it installed with the Docker folders that install created (and on the RHEL family Docker's repository, its signing key and what Docker added to firewalld), unless other containers still use Docker or you pass --keep-docker. Any of those packages that other software needs stays, like the container-selinux Podman shares. On a connected machine it leaves the dashboard first. It keeps your worlds and backups in /var/lib/playkeeper (reinstalling picks them up); --purge deletes them too and asks you to type a confirmation.
Recover or move a world: see docs/RECOVERY.md. Backups listed in the dashboard live on the same server unless you turn on copies somewhere else; download copies of the ones you care about.
Other commands: sudo playkeeper status, sudo playkeeper setup-code (a new setup code before an admin exists), sudo playkeeper reset-password <user>, sudo playkeeper reset-2fa <user> (turns off two-factor sign-in for a lost phone), sudo playkeeper join and sudo playkeeper leave (connect a machine to another dashboard, or disconnect it), and sudo playkeeper mcp (the AI tools over SSH).
From 0.4.4, Playkeeper counts how many machines run it, anonymously, so the project knows how many people use it and where to spend its time. The installer says so before it sends anything. Each machine sends exactly this, and Settings › Playkeeper › Usage stats shows yours field for field:
| Field | What it is |
|---|---|
id |
a random ID made on the machine for usage stats alone, tied to nothing else |
version |
the Playkeeper version, like 0.4.4 |
os, osVersion |
the system and its release, like ubuntu and 24.04 |
arch |
the CPU type, amd64 or arm64 |
source |
how Playkeeper got onto the machine: playkeeper.io (the install command there), github (get.sh straight from GitHub), mirror (get.sh from another location), tarball or source (a build that isn't a release) |
channel |
the code of a playkeeper.io/install/<code> command, if one was used |
kind |
dashboard, or joined for a machine connected to another dashboard |
test |
marks the project's own test installs, which aren't counted |
event, step |
from the installer: started once you accept its plan, then succeeded, or failed and the step that failed; or refused and the checks that turned it away, like memory, or existing-service-stopped for another Minecraft setup and its kind, or installed when it runs where Playkeeper already does |
address |
from a running machine: free (a playkeeper.me name), own (your own domain) or ip (none) |
servers, running |
from a running machine: how many Minecraft servers it has, and how many run |
reached |
from a running machine, from 0.4.18: the furthest step of its setup, account (the dashboard's first account made), server (a server came online), played (someone played on one of its servers, you included) or friends (a second, different player did), never who or how many |
The installer sends its reports while it installs, and nothing if you decline its plan. A running machine sends a heartbeat a minute after Playkeeper starts, then every 12 hours. From 0.4.16 a machine also sends one right after its first server comes online, and the dashboard's machine right after its first account is made, each only the first time, so the counts show how far a new install got even if its machine is gone within hours. From 0.4.18 it also sends one the first time someone plays on one of its servers, and the first time a second, different player does. They go to stats.playkeeper.io, the project's own service, whose code is in this repository (services/stats). It keeps each machine's random ID with what its reports say and the days it ran, never an IP address, and never learns a host name, a server name, or who plays or how many: only whether anyone has played yet, and whether a second player has.
Checking from the internet (from 0.4.18): a machine can't see its provider's firewall, so a server's Overview asks the same service whether friends can reach the server's port. The request names only the port, with no ID. The service connects back to the address the request came from, on that port alone, and asks for the server's status the way a game's server list does, reading no more of the answer than shows a Minecraft server answered, so never the players. It keeps nothing of a check. While usage stats are on, the Overview checks by itself, at most once an hour; with them off, it checks only when someone presses Check from the internet.
To turn usage stats off:
- Settings › Playkeeper › Usage stats: one switch for every machine of the dashboard.
- When installing:
curl -fsSL https://playkeeper.io/install | sudo DO_NOT_TRACK=1 shsends nothing, and the machine keeps them off; the switch can't turn them back on.PLAYKEEPER_USAGE_STATS=offdoes the same. Put the variable aftersudo, which drops variables set before it. - For a machine that's installed:
sudo systemctl edit playkeeper-agent, addEnvironment=DO_NOT_TRACK=1under[Service], thensudo systemctl restart playkeeper-agent.
Outside contributions are welcome, under the project's licence; CONTRIBUTING.md has the details and the PR checklist. Report security problems privately, as SECURITY.md describes, not in a public issue.
Stack: one Go binary (root agent on a Unix socket, unprivileged HTTPS panel, installer) with an embedded React/TypeScript UI built on coss ui components, SQLite, and a container per server from a pinned itzg/minecraft-server image (one per Java version, so each Minecraft version runs on the Java it was made for). Why: docs/decisions/0002-stack.md. How it fits together: docs/ARCHITECTURE.md.
On a stock Ubuntu 24.04 machine:
sudo apt-get update && sudo apt-get install -y git make curl ca-certificates xz-utils # only if missing
git clone https://github.com/CIYAhq/playkeeper.git && cd playkeeper
./scripts/setup.sh # pinned Go and Node into .tools/, npm ci
make check # lint, typecheck, Go, web and installer-script unit tests, the first-load budget (CI's check job)
make dev # agent + panel locally at https://localhost:8443 (uses your Docker)
make package # release tarballs for x86_64 and 64-bit ARM, get.sh, the stable-named copies and the (unsigned) release manifest in dist/
make e2e-vm # the full KVM rehearsal: install, play, backup, restore, one-line installRun make dev as your normal user with access to Docker (in the docker group), not as root: the server container runs as the calling user. ./scripts/negative-controls.sh removes each safety guard in turn (in a throwaway worktree) and checks that its test fails.
Several Minecraft Java servers of seven types, on one Linux VPS or more machines, x86_64 or 64-bit ARM, with plugins, mods and modpacks, a file browser and editor, guided setup, authenticated HTTPS management with your own address, a team with roles and two-factor sign-in, real operations and player analytics, schedules, portable backups with rules for what to keep, encrypted copies elsewhere and a guarded restore, in English (every string goes through a translation layer, ready for more languages). Other games, billing, VPS provisioning and taking over a world another panel runs on the VPS come later.
The interface is built from coss ui components (MIT, copied into the repository and restyled) with an original design, mascot and art. Ghost is a product reference, not our codebase or hosting model. See design, licensing and third-party components.
Playkeeper is free software under the GNU Affero General Public License, version 3 only (AGPL-3.0-only); see LICENSE and docs/LICENSING.md. The licences of the third-party code in the binary are reproduced in THIRD_PARTY_NOTICES, which every release tarball includes.
Not an official Minecraft product. Not approved by or associated with Mojang or Microsoft.
playkeeper.io is this repository's site/ folder, an nginx container (site/README.md): /install runs the latest release's get.sh, /sizing is the sizing guide, /t opens shared server templates in your own dashboard, and /demo/ is the live demo, the dashboard from web/ built with sample data (web/src/demo/).