# List all networks (admin only)
Source: https://simplecloud.app/docs/en/developer/api-reference/admin/list-all-networks-admin-only
https://controller.simplecloud.app/swagger/doc.json get /v0/admin/networks
List all networks. Requires admin access.
# Create a new blueprint
Source: https://simplecloud.app/docs/en/developer/api-reference/blueprints/create-a-new-blueprint
https://controller.simplecloud.app/swagger/doc.json post /v0/blueprints
Create a new blueprint for a network
# Delete a blueprint
Source: https://simplecloud.app/docs/en/developer/api-reference/blueprints/delete-a-blueprint
https://controller.simplecloud.app/swagger/doc.json delete /v0/blueprints
Delete an existing blueprint
# List blueprints
Source: https://simplecloud.app/docs/en/developer/api-reference/blueprints/list-blueprints
https://controller.simplecloud.app/swagger/doc.json get /v0/blueprints
Get a list of blueprints for a network
# Partially update a blueprint
Source: https://simplecloud.app/docs/en/developer/api-reference/blueprints/partially-update-a-blueprint
https://controller.simplecloud.app/swagger/doc.json patch /v0/blueprints
Partially update an existing blueprint
# Update a blueprint
Source: https://simplecloud.app/docs/en/developer/api-reference/blueprints/update-a-blueprint
https://controller.simplecloud.app/swagger/doc.json put /v0/blueprints
Update an existing blueprint
# Query current metric values
Source: https://simplecloud.app/docs/en/developer/api-reference/metrics/query-current-metric-values
https://controller.simplecloud.app/swagger/doc.json get /v0/metrics/query
Get the latest values for a metric, optionally grouped by a label
# Query logs with flexible filters
Source: https://simplecloud.app/docs/en/developer/api-reference/metrics/query-logs-with-flexible-filters
https://controller.simplecloud.app/swagger/doc.json post /v0/metrics/logs/query
Query logs using POST body with array-based filters for maximum flexibility
# Query metric time series
Source: https://simplecloud.app/docs/en/developer/api-reference/metrics/query-metric-time-series
https://controller.simplecloud.app/swagger/doc.json get /v0/metrics/query_range
Get time-bucketed metric values for charts, optionally grouped by a label
# Stream logs in real-time via SSE
Source: https://simplecloud.app/docs/en/developer/api-reference/metrics/stream-logs-in-real-time-via-sse
https://controller.simplecloud.app/swagger/doc.json get /v0/metrics/logs/stream
Server-Sent Events endpoint for real-time log streaming with filters
# Create network password
Source: https://simplecloud.app/docs/en/developer/api-reference/networks/create-network-password
https://controller.simplecloud.app/swagger/doc.json post /v0/networks/passwords
Create a new network password for the authenticated network
# Delete a network and all its resources
Source: https://simplecloud.app/docs/en/developer/api-reference/networks/delete-a-network-and-all-its-resources
https://controller.simplecloud.app/swagger/doc.json delete /v0/networks
Delete a network and cascade delete all associated resources (servers, groups, blueprints, etc.)
# Delete network password
Source: https://simplecloud.app/docs/en/developer/api-reference/networks/delete-network-password
https://controller.simplecloud.app/swagger/doc.json delete /v0/networks/passwords
Delete a network password from the authenticated network
# List network passwords
Source: https://simplecloud.app/docs/en/developer/api-reference/networks/list-network-passwords
https://controller.simplecloud.app/swagger/doc.json get /v0/networks/passwords
List all network passwords for the authenticated network
# Register a new network
Source: https://simplecloud.app/docs/en/developer/api-reference/networks/register-a-new-network
https://controller.simplecloud.app/swagger/doc.json post /v0/networks/register
Register a new network and generate credentials
# Update a network
Source: https://simplecloud.app/docs/en/developer/api-reference/networks/update-a-network
https://controller.simplecloud.app/swagger/doc.json patch /v0/networks
Update the authenticated network
# Verify network credentials
Source: https://simplecloud.app/docs/en/developer/api-reference/networks/verify-network-credentials
https://controller.simplecloud.app/swagger/doc.json post /v0/networks/verify
Verify if the provided network credentials are valid
# Create a new persistent server
Source: https://simplecloud.app/docs/en/developer/api-reference/persistent-servers/create-a-new-persistent-server
https://controller.simplecloud.app/swagger/doc.json post /v0/persistent-servers
Create a new persistent server for a network
# Delete a persistent server
Source: https://simplecloud.app/docs/en/developer/api-reference/persistent-servers/delete-a-persistent-server
https://controller.simplecloud.app/swagger/doc.json delete /v0/persistent-servers
Delete an existing persistent server
# Delete persistent server property keys
Source: https://simplecloud.app/docs/en/developer/api-reference/persistent-servers/delete-persistent-server-property-keys
https://controller.simplecloud.app/swagger/doc.json delete /v0/persistent-servers/properties
Delete specific property keys from a persistent server
# Execute a manual workflow for all running servers of a persistent server
Source: https://simplecloud.app/docs/en/developer/api-reference/persistent-servers/execute-a-manual-workflow-for-all-running-servers-of-a-persistent-server
https://controller.simplecloud.app/swagger/doc.json post /v0/persistent-servers/workflows/manual
Execute a configured manual workflow for all eligible running servers of a persistent server
# List persistent servers
Source: https://simplecloud.app/docs/en/developer/api-reference/persistent-servers/list-persistent-servers
https://controller.simplecloud.app/swagger/doc.json get /v0/persistent-servers
Get a list of persistent servers for a network
# Merge persistent server properties
Source: https://simplecloud.app/docs/en/developer/api-reference/persistent-servers/merge-persistent-server-properties
https://controller.simplecloud.app/swagger/doc.json patch /v0/persistent-servers/properties
Merge/update specific property keys for a persistent server (deep merge)
# Partially update a persistent server
Source: https://simplecloud.app/docs/en/developer/api-reference/persistent-servers/partially-update-a-persistent-server
https://controller.simplecloud.app/swagger/doc.json patch /v0/persistent-servers
Partially update an existing persistent server
# Replace persistent server properties
Source: https://simplecloud.app/docs/en/developer/api-reference/persistent-servers/replace-persistent-server-properties
https://controller.simplecloud.app/swagger/doc.json put /v0/persistent-servers/properties
Replace entire properties object for a persistent server
# Update a persistent server
Source: https://simplecloud.app/docs/en/developer/api-reference/persistent-servers/update-a-persistent-server
https://controller.simplecloud.app/swagger/doc.json put /v0/persistent-servers
Update an existing persistent server
# Connect player to server
Source: https://simplecloud.app/docs/en/developer/api-reference/players/connect-player-to-server
https://controller.simplecloud.app/swagger/doc.json post /v0/players/connect
Connect a player to a specific server, server group, or persistent server
# Delete player properties
Source: https://simplecloud.app/docs/en/developer/api-reference/players/delete-player-properties
https://controller.simplecloud.app/swagger/doc.json delete /v0/players/properties
Delete specific property keys
# Get client settings
Source: https://simplecloud.app/docs/en/developer/api-reference/players/get-client-settings
https://controller.simplecloud.app/swagger/doc.json get /v0/players/sessions/settings
Get client settings for an online player's current session
# Get current session
Source: https://simplecloud.app/docs/en/developer/api-reference/players/get-current-session
https://controller.simplecloud.app/swagger/doc.json get /v0/players/sessions/current
Get the current active session for an online player
# Get latest player profile
Source: https://simplecloud.app/docs/en/developer/api-reference/players/get-latest-player-profile
https://controller.simplecloud.app/swagger/doc.json get /v0/players/profiles/latest
Get the most recent profile (name/skin) for a player
# Get online player count
Source: https://simplecloud.app/docs/en/developer/api-reference/players/get-online-player-count
https://controller.simplecloud.app/swagger/doc.json get /v0/players/online/count
Get the count of online players
# Get player by name
Source: https://simplecloud.app/docs/en/developer/api-reference/players/get-player-by-name
https://controller.simplecloud.app/swagger/doc.json get /v0/players/name
Get a player by their name
# Get player by UUID
Source: https://simplecloud.app/docs/en/developer/api-reference/players/get-player-by-uuid
https://controller.simplecloud.app/swagger/doc.json get /v0/players/id
Get a player by their Minecraft UUID
# Get player online time
Source: https://simplecloud.app/docs/en/developer/api-reference/players/get-player-online-time
https://controller.simplecloud.app/swagger/doc.json get /v0/players/online-time
Get total online time for a player on this network
# Get player properties
Source: https://simplecloud.app/docs/en/developer/api-reference/players/get-player-properties
https://controller.simplecloud.app/swagger/doc.json get /v0/players/properties
Get custom properties for a player
# Kick a player
Source: https://simplecloud.app/docs/en/developer/api-reference/players/kick-a-player
https://controller.simplecloud.app/swagger/doc.json post /v0/players/kick
Kick a player from the network
# List online players
Source: https://simplecloud.app/docs/en/developer/api-reference/players/list-online-players
https://controller.simplecloud.app/swagger/doc.json get /v0/players/online
Get a list of online players
# List player profiles
Source: https://simplecloud.app/docs/en/developer/api-reference/players/list-player-profiles
https://controller.simplecloud.app/swagger/doc.json get /v0/players/profiles
Get a player's profile history (name/skin changes)
# List player sessions
Source: https://simplecloud.app/docs/en/developer/api-reference/players/list-player-sessions
https://controller.simplecloud.app/swagger/doc.json get /v0/players/sessions
Get session history for a player on this network
# List players
Source: https://simplecloud.app/docs/en/developer/api-reference/players/list-players
https://controller.simplecloud.app/swagger/doc.json get /v0/players
Get a list of players for a network with optional filtering
# Partially update a player
Source: https://simplecloud.app/docs/en/developer/api-reference/players/partially-update-a-player
https://controller.simplecloud.app/swagger/doc.json patch /v0/players
Partially update admin-managed player fields like online time and optionally reset first/last seen timestamps to now
# Patch player properties
Source: https://simplecloud.app/docs/en/developer/api-reference/players/patch-player-properties
https://controller.simplecloud.app/swagger/doc.json patch /v0/players/properties
Merge properties with existing ones
# Update client settings
Source: https://simplecloud.app/docs/en/developer/api-reference/players/update-client-settings
https://controller.simplecloud.app/swagger/doc.json put /v0/players/sessions/settings
Update client settings for an online player's current session
# Update player properties
Source: https://simplecloud.app/docs/en/developer/api-reference/players/update-player-properties
https://controller.simplecloud.app/swagger/doc.json put /v0/players/properties
Replace all player properties
# Bulk create plugin assignments
Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-assignments/bulk-create-plugin-assignments
https://controller.simplecloud.app/swagger/doc.json post /v0/plugin-assignments/bulk-create
Assign one or more plugins to multiple server groups and persistent servers atomically
# Bulk delete plugin assignments
Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-assignments/bulk-delete-plugin-assignments
https://controller.simplecloud.app/swagger/doc.json post /v0/plugin-assignments/bulk-delete
Delete multiple plugin assignments in one request
# Create a new plugin assignment
Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-assignments/create-a-new-plugin-assignment
https://controller.simplecloud.app/swagger/doc.json post /v0/plugin-assignments
Assign a plugin to a server group or persistent server. You can either provide a plugin_id to use an existing plugin, or provide plugin_name, source_type, and source_value to find or create the plugin automatically.
# Delete a plugin assignment
Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-assignments/delete-a-plugin-assignment
https://controller.simplecloud.app/swagger/doc.json delete /v0/plugin-assignments
Delete an existing plugin assignment
# List plugin assignments
Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-assignments/list-plugin-assignments
https://controller.simplecloud.app/swagger/doc.json get /v0/plugin-assignments
Get a list of plugin assignments for a network, optionally filtered by server group or persistent server
# Update a plugin assignment
Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-assignments/update-a-plugin-assignment
https://controller.simplecloud.app/swagger/doc.json put /v0/plugin-assignments
Update the plugin metadata for an existing assignment without deleting it first
# Bulk install a plugin collection on targets
Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-collection-assignments/bulk-install-a-plugin-collection-on-targets
https://controller.simplecloud.app/swagger/doc.json post /v0/plugin-collection-assignments/bulk-create
Install a plugin collection on multiple server groups and persistent servers atomically
# Delete a plugin collection installation
Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-collection-assignments/delete-a-plugin-collection-installation
https://controller.simplecloud.app/swagger/doc.json delete /v0/plugin-collection-assignments
Delete a plugin collection installation without deleting the normal plugin assignments created from it
# Install a plugin collection on a target
Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-collection-assignments/install-a-plugin-collection-on-a-target
https://controller.simplecloud.app/swagger/doc.json post /v0/plugin-collection-assignments
Install a plugin collection on a server group or persistent server and materialize normal plugin assignments
# List plugin collection installations
Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-collection-assignments/list-plugin-collection-installations
https://controller.simplecloud.app/swagger/doc.json get /v0/plugin-collection-assignments
Get plugin collection installations for a network, optionally filtered by target
# Reapply plugin collection assignments
Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-collection-assignments/reapply-plugin-collection-assignments
https://controller.simplecloud.app/swagger/doc.json post /v0/plugin-collection-assignments/reapply
Materialize missing plugin assignments from existing plugin collection assignments
# Add a plugin to a plugin collection
Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-collection-plugins/add-a-plugin-to-a-plugin-collection
https://controller.simplecloud.app/swagger/doc.json post /v0/plugin-collection-plugins
Add a plugin reference to a plugin collection without modifying existing assignments
# Delete a plugin from a plugin collection
Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-collection-plugins/delete-a-plugin-from-a-plugin-collection
https://controller.simplecloud.app/swagger/doc.json delete /v0/plugin-collection-plugins
Delete a plugin from a plugin collection without deleting existing assignments created from it
# List plugins in a plugin collection
Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-collection-plugins/list-plugins-in-a-plugin-collection
https://controller.simplecloud.app/swagger/doc.json get /v0/plugin-collection-plugins
Get the plugins configured for a plugin collection
# Create a plugin collection
Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-collections/create-a-plugin-collection
https://controller.simplecloud.app/swagger/doc.json post /v0/plugin-collections
Create a new plugin collection for a network
# List plugin collections
Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-collections/list-plugin-collections
https://controller.simplecloud.app/swagger/doc.json get /v0/plugin-collections
Get a list of plugin collections for a network
# Update a plugin collection
Source: https://simplecloud.app/docs/en/developer/api-reference/plugin-collections/update-a-plugin-collection
https://controller.simplecloud.app/swagger/doc.json put /v0/plugin-collections
Update an existing plugin collection
# Events API
Source: https://simplecloud.app/docs/en/developer/api/events
Subscribe to group, server, persistent server, and blueprint events
## Subscribe to an event
The examples use the shared `CloudApi` client created in [Installation](/docs/en/developer/installation) and belong inside your plugin's methods.
```java theme={null}
Subscription subscription = api.event().server().onStateChanged(event -> {
String serverId = event.getServerId();
// React to the state change.
});
```
Keep the returned `Subscription` and close it when your plugin stops. The [event handling guide](/docs/en/developer/guides/event-handling) shows the complete plugin lifecycle and how to safely interact with your server platform from a callback.
## Choose an event category
| Category | Subscription methods | Callback types |
| -------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `group()` | `onCreated`, `onUpdated`, `onDeleted` | `GroupCreatedEvent`, `GroupUpdatedEvent`, `GroupDeletedEvent` |
| `server()` | `onStarted`, `onStopped`, `onStateChanged`, `onUpdated`, `onDeleted` | `ServerStartedEvent`, `ServerStoppedEvent`, `ServerStateChangedEvent`, `ServerUpdatedEvent`, `ServerDeletedEvent` |
| `persistentServer()` | `onCreated`, `onStarted`, `onStopped`, `onUpdated`, `onDeleted` | `PersistentServerCreatedEvent`, `PersistentServerStartedEvent`, `PersistentServerStoppedEvent`, `PersistentServerUpdatedEvent`, `PersistentServerDeletedEvent` |
| `blueprint()` | `onCreated`, `onUpdated`, `onDeleted` | `BlueprintCreatedEvent`, `BlueprintUpdatedEvent`, `BlueprintDeletedEvent` |
Server events describe individual server instances. Persistent server events describe changes to the persistent server itself, such as it being updated or starting a server instance.
## Keep state accurate
Events notify you that something changed; query APIs provide the current state. Subscriptions only receive live events, so query the resource when your plugin starts or when missing an event would make its state incorrect.
Close each subscription when you no longer need it. Both `close()` and `unsubscribe()` stop future delivery and can be called more than once.
## Read callback data
Every callback provides `getNetworkId()` and an ISO 8601 timestamp through `getTimestamp()`. The remaining getters depend on the event type.
Prefer the stable ID getter when identifying a resource.
Some event payloads omit the embedded model. In that case, model getters such as `getServer()`, `getGroup()`, and `getBlueprint()` throw `IllegalStateException`.
Query the matching resource API when you need its current data.
| Callback type | Additional getters |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `ServerStartedEvent` | `getServerId()`, `getServerGroupId()`, `getServer()` |
| `ServerStoppedEvent` | `getServerId()`, `getServerGroupId()`, `getServer()`, `getCrashed()`, `getExitCode()` (`Integer` or `null`), `getReason()` (`String` or `null`) |
| `ServerStateChangedEvent` | `getServerId()`, `getOldState()`, `getNewState()`, `getServer()` |
| `ServerUpdatedEvent` | `getServerId()`, `getServerGroupId()`, `getServer()` |
| `ServerDeletedEvent` | `getServerId()`, `getServerGroupId()`, `getServer()` |
| Callback type | Additional getters |
| ------------------- | ------------------------------------------------------ |
| `GroupCreatedEvent` | `getServerGroupId()`, `getGroup()` |
| `GroupUpdatedEvent` | `getServerGroupId()`, `getGroup()` |
| `GroupDeletedEvent` | `getServerGroupId()`, `getName()` (`String` or `null`) |
| Callback type | Additional getters |
| ------------------------------ | --------------------------------------------------------------- |
| `PersistentServerCreatedEvent` | `getPersistentServerId()`, `getName()` (`String` or `null`) |
| `PersistentServerStartedEvent` | `getPersistentServerId()`, `getServerId()` (`String` or `null`) |
| `PersistentServerStoppedEvent` | `getPersistentServerId()`, `getServerId()` (`String` or `null`) |
| `PersistentServerUpdatedEvent` | `getPersistentServerId()`, `getName()` (`String` or `null`) |
| `PersistentServerDeletedEvent` | `getPersistentServerId()`, `getName()` (`String` or `null`) |
| Callback type | Additional getters |
| ----------------------- | ---------------------------------------------------- |
| `BlueprintCreatedEvent` | `getBlueprintId()`, `getBlueprint()` |
| `BlueprintUpdatedEvent` | `getBlueprintId()`, `getBlueprint()` |
| `BlueprintDeletedEvent` | `getBlueprintId()`, `getName()` (`String` or `null`) |
# Groups API
Source: https://simplecloud.app/docs/en/developer/api/groups
Create, query, update, and delete server groups
## Create a group
A group applies the same software, resources, and scaling behavior to each server it creates.
The examples use the shared `CloudApi` client created in [Installation](/docs/en/developer/installation) and belong inside your plugin's methods.
This example creates a Paper lobby group and its blueprint. SimpleCloud keeps one lobby running and can scale the group up to three servers while maintaining 20 available player slots.
```java theme={null}
CreateGroupRequest request = CreateGroupRequest.builder()
.name("lobby")
.type(GroupServerType.SERVER)
.minMemory(1024)
.maxMemory(2048)
.maxPlayers(100)
.createBlueprint(CreateBlueprintRequest.builder()
.configurator("paper")
.serverSoftware("paper")
.minecraftVersion("1.21.11")
.build())
.scaling(ScalingConfig.builder()
.scalingMode(ScalingMode.SLOTS)
.minServers(1)
.maxServers(3)
.availableSlots(20)
.build())
.build();
api.group().createGroup(request)
.thenAccept(group -> System.out.println(
"Created " + group.getName() + " with ID " + group.getServerGroupId()
));
```
The group name is also used for the new blueprint. To use a blueprint that already exists, replace `createBlueprint(...)` with:
```java theme={null}
.source(SourceConfig.builder()
.type(SourceType.BLUEPRINT)
.blueprint("blueprint-uuid")
.build())
```
Do not set both `createBlueprint` and an existing blueprint or image source.
Use up to 100 ASCII letters, digits, underscores, or hyphens (`[A-Za-z0-9_-]`). Group names are unique within the network.
Name matching is case-insensitive, so `Lobby` and `lobby` identify the same group. Creating or renaming a group to a case-only variation of an existing name returns `409 Conflict`.
A group and a persistent server may share a name.
`SERVER` for game servers or `PROXY` for proxies. Defaults to `SERVER`.
Minimum memory in MB.
Maximum memory in MB.
Player limit per server. Defaults to `50`.
Whether the group may create servers. Defaults to `true`.
Group priority.
Host selection settings.
Minimum and maximum servers and scaling behavior.
Existing blueprint or container image used by the group.
Blueprint to create with the group.
Lifecycle and manual workflows.
Custom group properties.
Tags used to organize and filter groups.
## Find groups
Look up a group by name or ID:
```java theme={null}
api.group().getGroupByName("lobby")
.thenAccept(group -> System.out.println(group.getServerGroupId()));
api.group().getGroupById("group-uuid")
.thenAccept(group -> System.out.println(group.getName()));
```
Both methods complete exceptionally when the group does not exist. Name lookups are case-insensitive.
Use `GroupQuery` to filter the group list by type, tag, or result limit:
```java theme={null}
GroupQuery query = GroupQuery.create()
.filterByType(GroupServerType.SERVER)
.filterByTag("production")
.limit(25);
api.group().getAllGroups(query)
.thenAccept(groups -> groups.forEach(group ->
System.out.println(group.getName())
));
```
Call `getAllGroups()` without a query to return every group.
## Update a group
`UpdateGroupRequest` changes only the fields you set:
```java theme={null}
UpdateGroupRequest update = UpdateGroupRequest.builder()
.maxPlayers(120)
.build();
api.group().updateGroup("group-uuid", update)
.thenAccept(group -> System.out.println("Updated " + group.getName()));
```
You can update `name`, `type`, `minMemory`, `maxMemory`, `maxPlayers`, `active`, `priority`, `deployment`, `scaling`, `source`, `workflows`, `properties`, and `tags`.
When updating a nested object such as `ScalingConfig`, provide all values you want it to contain. Use the property methods below when you only want to merge individual properties.
## Manage group properties
Group properties store custom data for your plugins. Updates merge with the existing map.
```java theme={null}
Map properties = Map.of(
"gameMode", "ADVENTURE",
"region", "eu-west"
);
api.group().updateGroupProperties("group-uuid", properties)
.thenAccept(updated -> System.out.println("Properties: " + updated));
api.group().deleteGroupProperty("group-uuid", "region")
.thenAccept(remaining -> System.out.println("Properties: " + remaining));
```
Use `deleteGroupProperties` to remove several keys at once. Each property method returns the resulting map.
## Start another server
Request one additional server when a specific application action needs another instance:
```java theme={null}
api.group().getGroupByName("lobby")
.thenCompose(api.group()::requestServerStart)
.thenRun(() -> System.out.println("Start requested"));
```
This queues one start request without changing the group's scaling configuration. Use the [Servers API](/docs/en/developer/api/servers) or server events when your plugin needs to wait for the new server.
### Inspect the start queue
The queue shows pending and failed manual start requests:
```java theme={null}
api.group().getServerStartQueue()
.thenAccept(queue -> {
GroupStartQueueEntry lobby = queue.findByServerGroupName("lobby");
if (lobby == null) {
return;
}
lobby.getStarts().stream()
.filter(start -> start.getStatus() == GroupStartQueueItemStatus.FAILED)
.forEach(start -> System.err.println(start.getFailureReason()));
});
```
`findByServerGroupId` and `findByServerGroupName` return `null` when the queue has no entry for the group.
Clear pending start requests for a group with:
```java theme={null}
api.group().clearServerStartQueue("group-uuid");
```
This does not stop servers that have already been created.
`GroupStartQueue` contains totals across every group and a list of `GroupStartQueueEntry` objects.
Number of group entries.
Number of pending starts.
Number of failed starts.
Total number of start requests.
Queue entries grouped by server group.
Each `GroupStartQueueEntry` provides the group ID and name, its start counts, and a `starts` list. A `GroupStartQueueItem` provides its ID, creation time, status, and failure reason. Its status is `PENDING`, `FAILED`, or `UNKNOWN`.
## Delete a group
```java theme={null}
api.group().deleteGroup("group-uuid");
```
Deactivate the group first so it cannot replace stopped instances. Stop its servers, wait for them to stop, then delete the group.
## Group model reference
The following fields are available through `Group` getters.
Unique group identifier.
Group name.
`SERVER`, `PROXY`, or `UNKNOWN_SERVER`.
Minimum memory in MB.
Maximum memory in MB.
Player limit per server.
Whether the group may create servers.
Group priority.
Host selection configuration.
Scaling configuration.
Blueprint or container image source.
Lifecycle and manual workflows.
Custom group properties.
Group tags.
Creation timestamp in ISO 8601 format.
Last-update timestamp in ISO 8601 format.
Minimum number of servers to maintain.
Maximum number of servers the group may create.
`SLOTS` is the dashboard's **Slots** mode and maintains free capacity. `PLAYERS` is the dashboard's **Servers** mode and starts servers from player utilization.
Free player slots to maintain in `SLOTS` mode.
Player utilization threshold between `0` and `1`.
Scale-down settings.
`SLOTS` can start and stop servers. `PLAYERS` only starts servers; it does not stop extra instances automatically.
## Group server types
| Value | Description |
| ---------------- | -------------------------------------------- |
| `SERVER` | Game server, such as Paper or Spigot |
| `PROXY` | Proxy server, such as Velocity or BungeeCord |
| `UNKNOWN_SERVER` | Unknown server type returned by the API |
# Persistent servers API
Source: https://simplecloud.app/docs/en/developer/api/persistent-servers
Create, query, update, and delete persistent servers
## Create a persistent server
A persistent server keeps one server configuration and does not scale to multiple instances like a group.
The examples use the shared `CloudApi` client created in [Installation](/docs/en/developer/installation) and belong inside your plugin's methods.
This example creates `survival-1` with a new Paper blueprint. Because the persistent server is active, SimpleCloud starts its instance and replaces it after a stop.
```java theme={null}
CreatePersistentServerRequest request = CreatePersistentServerRequest.builder()
.name("survival-1")
.type(GroupServerType.SERVER)
.minMemory(2048)
.maxMemory(4096)
.maxPlayers(80)
.createBlueprint(CreateBlueprintRequest.builder()
.configurator("paper")
.serverSoftware("paper")
.minecraftVersion("1.21.11")
.build())
.active(true)
.serverhostId("serverhost-uuid")
.tags(List.of("survival", "production"))
.build();
api.persistentServer().createPersistentServer(request)
.thenAccept(server -> System.out.println(
"Created " + server.getName() + " with ID " + server.getPersistentServerId()));
```
To use an existing blueprint instead, replace `createBlueprint(...)` with a source:
```java theme={null}
.source(SourceConfig.builder()
.type(SourceType.BLUEPRINT)
.blueprint("blueprint-uuid")
.build())
```
Set either `source` or `createBlueprint`, not both.
Use up to 100 ASCII letters, digits, underscores, or hyphens (`[A-Za-z0-9_-]`). Persistent server names are unique within the network.
Name matching is case-insensitive, so `Survival-1` and `survival-1` identify the same persistent server. Creating or renaming a persistent server to a case-only variation of an existing name returns `409 Conflict`.
A persistent server and a group may share a name.
`SERVER` or `PROXY`. Defaults to `SERVER`.
Minimum memory in MB.
Maximum memory in MB.
Player limit. Defaults to `50`.
Blueprint to create for this persistent server.
Existing blueprint or container image to use. Do not set this together with `createBlueprint`.
Whether SimpleCloud should keep an instance running. Defaults to `true`.
Persistent server priority.
ID of the assigned serverhost.
Lifecycle and manual workflows.
Custom properties.
Tags used to organize and filter persistent servers.
## Find persistent servers
Find one persistent server by name or ID:
```java theme={null}
api.persistentServer().getPersistentServerByName("survival-1")
.thenAccept(server -> System.out.println(server.getPersistentServerId()));
api.persistentServer().getPersistentServerById("persistent-server-uuid")
.thenAccept(server -> System.out.println(server.getName()));
```
Both methods complete exceptionally when no persistent server matches. Name lookups are case-insensitive.
Use a query to filter the list:
```java theme={null}
PersistentServerQuery query = PersistentServerQuery.create()
.filterByActive(true)
.filterByTags("survival", "production")
.limit(20);
api.persistentServer().getAllPersistentServers(query)
.thenAccept(servers -> servers.forEach(server ->
System.out.println(server.getName() + ": " + server.getPlayerCount())));
```
The query can filter by tags, active state, and serverhost ID. Call `getAllPersistentServers()` without a query to return every persistent server.
## Update a persistent server
Only fields set on `UpdatePersistentServerRequest` are changed:
```java theme={null}
UpdatePersistentServerRequest update = UpdatePersistentServerRequest.builder()
.maxMemory(6144)
.maxPlayers(100)
.build();
api.persistentServer()
.updatePersistentServer("persistent-server-uuid", update)
.thenAccept(server -> System.out.println("Updated " + server.getName()));
```
You can update the name, type, memory, player limit, active state, priority, assigned serverhost, source, workflows, properties, and tags.
## Manage properties
Use the property methods to change custom properties without updating the rest of the configuration:
```java theme={null}
api.persistentServer().updatePersistentServerProperties(
"persistent-server-uuid",
Map.of("gameMode", "SURVIVAL", "region", "eu-central")
).thenAccept(properties -> System.out.println("Properties: " + properties));
api.persistentServer()
.deletePersistentServerProperty("persistent-server-uuid", "region")
.thenAccept(properties -> System.out.println("Properties: " + properties));
```
`updatePersistentServerProperties` merges the supplied values with the existing properties. You can also update one property or delete multiple properties.
## Delete a persistent server
```java theme={null}
api.persistentServer()
.deletePersistentServer("persistent-server-uuid")
.thenRun(() -> System.out.println("Deleted persistent server"));
```
Deactivate the persistent server first, stop its instance, and delete the configuration after the instance stops. Its files remain on the serverhost.
## Persistent server model
`PersistentServer` extends `ServerBase` and provides the following fields.
Unique persistent server ID.
Persistent server name.
`SERVER`, `PROXY`, or `UNKNOWN_SERVER`.
Minimum memory in MB.
Maximum memory in MB.
Player limit.
Whether SimpleCloud should keep an instance running.
Persistent server priority.
Assigned serverhost ID.
Current player count, or `0` when no instance is running.
Blueprint or container image source.
Lifecycle and manual workflows.
Custom properties.
Tags used for filtering and organization.
Creation timestamp in ISO 8601 format.
Last update timestamp in ISO 8601 format.
Use `api.server()` to work with the running instance. Its `getPersistentServerId()` method links it back to this configuration.
# Players API
Source: https://simplecloud.app/docs/en/developer/api/players
Look up players, inspect presence, transfer or kick them, and manage player data
## Look up a player
The examples use the shared `CloudApi` client created in [Installation](/docs/en/developer/installation) and belong inside your plugin's methods.
Prefer a player's UUID when you know it because usernames can change.
Look up a player by UUID and check whether they are online before using their current server:
```java theme={null}
api.player().get(playerId).thenAccept(player -> {
if (player == null || !player.isOnline()) {
logger.info("Player is offline");
return;
}
String serverName = player.getConnectedServerName();
logger.info(serverName == null
? "Player is connected through a proxy"
: "Player is on " + serverName);
});
```
`get(UUID)` returns `null` when SimpleCloud has no stored player with that UUID. You can also look up a player by their case-insensitive username:
```java theme={null}
api.player().get("Steve");
```
A `CloudPlayer` contains the state recorded when you queried it. Fetch the player again when a later action depends on their current presence.
## List online players
Use the online player list when you need the players themselves, or request only the count:
```java theme={null}
api.player().getOnlinePlayers();
api.player().getOnlinePlayerCount();
```
The list is empty and the count is `0` when no players are online.
## Inspect player data
| Method | Value |
| -------------------------- | -------------------------------------------- |
| `getUniqueId()` | Player UUID |
| `getName()` | Username |
| `getDisplayName()` | Stored display name |
| `isOnline()` | Whether the player was online when queried |
| `getConnectedProxyName()` | Connected proxy name, or `null` |
| `getConnectedServerName()` | Registered backend server name, or `null` |
| `getSessionId()` | Active session ID, or `null` |
| `getFirstSeen()` | First-seen ISO-8601 timestamp, or `null` |
| `getLastSeen()` | Last-seen ISO-8601 timestamp, or `null` |
| `getOnlineTimeSeconds()` | Accumulated online time |
| `getProperties()` | Immutable custom properties, or an empty map |
## Connect a player
Call `connect(...)` with the server name registered on the player's proxy, such as `lobby-1`. Do not pass the server UUID.
Connecting players requires the `simplecloud-api` provider on the Velocity or BungeeCord proxy.
| Result | Meaning |
| ------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `SUCCESS` | The player connected to the target server. |
| `SERVER_NOT_FOUND` | The proxy does not know the target server name. |
| `ALREADY_CONNECTED` | The player is already connected to the target server. |
| `PLAYER_NOT_FOUND` | Not currently returned by `connect(...)`; the transfer guide uses it when its player lookup finds no online player. |
| `CONNECTION_FAILED` | The connection could not be completed, including when the player is no longer available. |
See [Transfer a player to another server](/docs/en/developer/guides/player-transfer) for a complete transfer workflow.
## Kick a player
Pass an Adventure component as the reason shown to the player:
```java theme={null}
player.kick(Component.text("Server restarting"));
```
Kicking players requires the `simplecloud-api` provider on the Velocity or BungeeCord proxy.
## Send Adventure content
`CloudPlayer` implements Adventure's `Audience`, so you can send messages, action bars, titles, sounds, boss bars, books, and player-list headers and footers.
```java theme={null}
player.sendMessage(Component.text("Welcome!"));
player.sendActionBar(Component.text("Combat mode enabled"));
player.showTitle(Title.title(
Component.text("Welcome"),
Component.text("to the server")
));
```
Remote Adventure content requires the `simplecloud-api` provider on the player's Paper or Folia server.
## Manage online time and properties
Player properties store custom string values for your plugins.
| Task | Method |
| ------------------------- | ----------------------------------------------------------------------------------------- |
| Read online time | `getOnlineTimeSeconds(playerId)` |
| Set online time | `setOnlineTimeSeconds(playerId, seconds)` |
| Reset online time | `resetOnlineTime(playerId)` |
| Add or remove time | `addOnlineTimeSeconds(playerId, seconds)` or `removeOnlineTimeSeconds(playerId, seconds)` |
| Set one property | `updatePlayerProperty(playerId, key, value)` |
| Set several properties | `updatePlayerProperties(playerId, properties)` |
| Delete one property | `deletePlayerProperty(playerId, key)` |
| Delete several properties | `deletePlayerProperties(playerId, keys)` |
Online time must be between `0` and `Integer.MAX_VALUE` seconds. The add and remove helpers read the current value before writing the result, so concurrent changes can overwrite one another.
Property updates merge the supplied values with the existing map, while delete methods remove only the specified keys. The merged properties must fit within 4 KB when encoded as JSON.
# Servers API
Source: https://simplecloud.app/docs/en/developer/api/servers
Find, inspect, update, and stop running server instances
## Find available capacity
The examples use the shared `CloudApi` client created in [Installation](/docs/en/developer/installation) and belong inside your plugin's methods.
Use `ServerQuery` to find instances by source, state, host, or numerical ID. This example calculates the reported free slots across playable lobby servers:
```java theme={null}
ServerQuery query = ServerQuery.create()
.filterByServerGroupName("lobby")
.filterByState(ServerState.AVAILABLE, ServerState.INGAME);
api.server().getAllServers(query)
.thenApply(servers -> servers.stream()
.filter(server -> server.getPlayerCount() != null)
.mapToInt(server -> Math.max(
0,
server.getMaxPlayers() - server.getPlayerCount()
))
.sum())
.thenAccept(capacity ->
System.out.println("Lobby capacity: " + capacity));
```
The result is a snapshot, not a reservation. If you use it to choose where a player should connect, keep the routing policy in your application and handle the connection result. See [Route players with autoscaling](/docs/en/developer/guides/server-management) for a complete routing workflow.
Call `getAllServers()` without a query to return every instance, or use `getServersByGroup("lobby")` as a group-name shortcut. List methods return an empty list when nothing matches.
Repeated calls to a multi-value filter add values to the query.
Match one or more group IDs.
Match one or more lifecycle states.
Match instances running on one serverhost.
Match the instance of one persistent server.
Match `SERVER` or `PROXY` sources.
Match one or more group or persistent server names.
Match sources with any supplied tag.
Match one or more numerical IDs.
Sort by `created_at`, `updated_at`, `numerical_id`, or `state`.
Use `asc` or `desc`.
## Find one server
Look up an instance by its unique ID, or by its group name and numerical ID:
```java theme={null}
api.server().getServerById("server-uuid")
.thenAccept(server -> System.out.println(server.getState()));
api.server().getServerByNumericalId("lobby", 1)
.thenAccept(server -> System.out.println(server.getServerId()));
```
These lookups complete exceptionally when no matching server exists.
### Get the current server
Code running inside a SimpleCloud-managed server can resolve its own instance:
```java theme={null}
api.server().getCurrentServer()
.thenAccept(server -> System.out.println(server.getServerId()));
```
`getCurrentServer()` uses the `SIMPLECLOUD_UNIQUE_ID` environment variable and completes exceptionally when the current process is not associated with an instance.
## Access the owning configuration
Every instance belongs to either a group or a persistent server. `getServerBase()` provides their shared configuration, while `getGroup()` and `getPersistentServer()` expose source-specific fields.
To change how instances are created, update the owning [group](/docs/en/developer/api/groups) or [persistent server](/docs/en/developer/api/persistent-servers) instead.
```java theme={null}
api.server().getServerById("server-uuid")
.thenAccept(server -> {
if (server.isFromGroup()) {
System.out.println("Group: " + server.getGroup().getName());
} else {
System.out.println(
"Persistent server: " +
server.getPersistentServer().getName()
);
}
System.out.println(
"Configured slots: " + server.getServerBase().getMaxPlayers()
);
});
```
Only one of `getGroup()` and `getPersistentServer()` is available for an instance. Avoid the deprecated `getServerGroup()`, which throws for persistent server instances.
## Update an instance
`UpdateServerRequest` changes only the fields you set:
```java theme={null}
UpdateServerRequest update = UpdateServerRequest.builder()
.maxPlayers(64)
.maxMemory(2048)
.build();
api.server().updateServer("server-uuid", update)
.thenAccept(server ->
System.out.println("Updated slots: " + server.getMaxPlayers()));
```
The builder supports `state`, `properties`, `minMemory`, `maxMemory`, and `maxPlayers`. Changes apply to this instance, not its owning configuration. `playerCount` is a runtime observation reported by the serverhost and is read-only over the HTTP API; sending it in an update request is rejected as an unknown field. The platform normally reports `state`; only set it when your integration owns that reporting.
## Manage instance properties
Properties attach application data to one instance. Updates merge with the existing map.
```java theme={null}
api.server().updateServerProperties(
"server-uuid",
Map.of("gameMode", "competitive", "map", "castle")
);
api.server().deleteServerProperty("server-uuid", "map");
```
Use `updateServerProperty` to set one key and `deleteServerProperties` to remove several keys. Each method returns the resulting property map.
## Stop an instance
```java theme={null}
api.server().stopServer("server-uuid")
.thenRun(() -> System.out.println("Shutdown initiated"));
```
The future completes when SimpleCloud initiates the stop, not when cleanup finishes. Use [server state events](/docs/en/developer/api/events) if your plugin must observe the later lifecycle transitions.
Stopping an instance does not disable its group or persistent server. SimpleCloud may create a replacement to maintain the source configuration. Change that configuration first when the server must stay offline.
## Server model
Unique instance ID.
Numerical ID within the source group or persistent server.
Source group ID, or `null` for a persistent server instance.
Source persistent server ID, or `null` for a group instance.
Serverhost running the instance.
Network that owns the instance.
Assigned IP address, or `null` before one is available.
Assigned port, or `null` before one is available.
Minimum memory in MB.
Maximum memory in MB.
Current CPU usage percentage, or `null` when unavailable.
Current memory usage in MB, or `null` when unavailable.
Current connected player count, or `null` when unavailable.
Player limit for the instance.
Current lifecycle state.
Creation timestamp in ISO 8601 format.
Last update timestamp in ISO 8601 format.
Last activity timestamp in ISO 8601 format, or `null` when unavailable.
Instance properties, or `null` when none are available.
Reserved accessor. The current implementation returns `null`; use the source configuration instead.
Shared configuration from the source group or persistent server.
Source group, or `null` for a persistent server instance.
Source persistent server, or `null` for a group instance.
## Server states
| State | Meaning |
| --------------- | --------------------------------------------------- |
| `UNKNOWN_STATE` | Unknown or unspecified. |
| `PREPARING` | SimpleCloud is preparing the instance. |
| `STARTING` | The server process is starting. |
| `AVAILABLE` | Ready to accept connections. |
| `INGAME` | Running with active players. |
| `STOPPING` | Shutdown is in progress. |
| `CLEANUP` | The process has stopped and cleanup is in progress. |
# React to server availability
Source: https://simplecloud.app/docs/en/developer/guides/event-handling
Run your plugin logic when a server becomes available
## Listen for available servers
The listener uses the `CloudApi` client your plugin already owns and notifies your application code when a server becomes available:
```java ServerAvailabilityListener.java theme={null}
package com.example;
import app.simplecloud.api.CloudApi;
import app.simplecloud.api.event.Subscription;
import app.simplecloud.api.server.ServerState;
public final class ServerAvailabilityListener implements AutoCloseable {
private final Subscription subscription;
public ServerAvailabilityListener(
CloudApi cloudApi,
Runnable onServerAvailable
) {
subscription = cloudApi.event().server().onStateChanged(event -> {
if (event.getNewState() == ServerState.AVAILABLE) {
onServerAvailable.run();
}
});
}
@Override
public void close() {
subscription.close();
}
}
```
Create the listener when your plugin starts and connect it to the work that is waiting for an available server:
```java theme={null}
serverAvailability = new ServerAvailabilityListener(
cloudApi,
() -> matchmaking.refreshAvailableServers()
);
```
Treat the callback as a signal to retry waiting work or refresh the destinations known to your routing system.
Events only report changes that happen after you subscribe. If your plugin also needs the current state when it starts, load it separately through the [Servers API](/docs/en/developer/api/servers).
If the callback changes Bukkit, Folia, Velocity, or BungeeCord state, schedule that platform-specific work through the platform's scheduler.
## Close the listener
Close the listener when your plugin stops, before closing the shared `CloudApi` client:
```java theme={null}
if (serverAvailability != null) {
serverAvailability.close();
}
```
This stops future callbacks. The listener does not close the shared `CloudApi` client.
See the [Events API reference](/docs/en/developer/api/events) for the other event categories and callback types.
# Transfer a player to another server
Source: https://simplecloud.app/docs/en/developer/guides/player-transfer
Connect an online player to a known server and handle the result
## Transfer the player
Before you begin, [install the Cloud API](/docs/en/developer/installation), require the `simplecloud-api` platform plugin, and create one shared `CloudApi` client. Install `simplecloud-api` on every proxy that may handle the player because that proxy performs the transfer.
Pass the registered server name, such as `lobby-1`, rather than the UUID returned by `Server.getServerId()`.
Look up the player by UUID, confirm they are online, and connect them to the registered server name:
```java PlayerTransferService.java theme={null}
import app.simplecloud.api.CloudApi;
import app.simplecloud.api.player.CloudPlayer;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;
import java.util.logging.Logger;
public final class PlayerTransferService {
private final CloudApi api;
private final Logger logger;
public PlayerTransferService(CloudApi api, Logger logger) {
this.api = api;
this.logger = logger;
}
public CompletableFuture transfer(
UUID playerId,
String registeredServerName
) {
return api.player().get(playerId).thenCompose(player -> {
if (player == null || !player.isOnline()) {
return CompletableFuture.completedFuture(
CloudPlayer.ConnectResult.PLAYER_NOT_FOUND
);
}
return player.connect(registeredServerName);
});
}
public void transferToLobby(UUID playerId) {
transfer(playerId, "lobby-1")
.thenAccept(result -> {
switch (result) {
case SUCCESS, ALREADY_CONNECTED ->
logger.info("Player is connected to lobby-1");
case SERVER_NOT_FOUND ->
logger.warning("lobby-1 is not registered on the proxy");
case PLAYER_NOT_FOUND ->
logger.info("Player is no longer online");
case CONNECTION_FAILED ->
logger.warning("Could not connect player to lobby-1");
}
})
.exceptionally(error -> {
logger.log(Level.WARNING, "Could not transfer player", error);
return null;
});
}
}
```
Create one `PlayerTransferService` from your plugin's shared `CloudApi` and logger. Call `transferToLobby(...)` from your command or matchmaking flow.
The service returns `PLAYER_NOT_FOUND` when its lookup finds no online player. If the player disconnects after that check, `connect(...)` returns `CONNECTION_FAILED`.
## Connection results
| Result | Meaning |
| ------------------- | ---------------------------------------------------------- |
| `SUCCESS` | The player connected to the destination. |
| `ALREADY_CONNECTED` | The player is already connected to the destination. |
| `SERVER_NOT_FOUND` | The supplied name is not registered on the player's proxy. |
| `PLAYER_NOT_FOUND` | The lookup found no online player. |
| `CONNECTION_FAILED` | The proxy could not complete the connection. |
If your plugin needs to find an available destination first, see [Route players with autoscaling](/docs/en/developer/guides/server-management).
# Route players with autoscaling
Source: https://simplecloud.app/docs/en/developer/guides/server-management
Send a player to an available server without managing group capacity yourself
## Route a player to a group
Let SimpleCloud manage the number of servers in a group. This workflow only chooses from instances that are ready now.
The following router finds playable servers in a group, ignores full instances, and attempts one connection. It returns `NoCapacity` when no suitable server is available and `ConnectionAttempted` with the result from `CloudPlayer.connect` otherwise.
```java GroupRouter.java theme={null}
package com.example;
import app.simplecloud.api.CloudApi;
import app.simplecloud.api.player.CloudPlayer;
import app.simplecloud.api.server.Server;
import app.simplecloud.api.server.ServerQuery;
import app.simplecloud.api.server.ServerState;
import java.util.Comparator;
import java.util.concurrent.CompletableFuture;
public final class GroupRouter {
private final CloudApi api;
public GroupRouter(CloudApi api) {
this.api = api;
}
public CompletableFuture routeToGroup(
CloudPlayer player,
String groupName
) {
ServerQuery query = ServerQuery.create()
.filterByServerGroupName(groupName)
.filterByState(ServerState.AVAILABLE, ServerState.INGAME);
return api.server().getAllServers(query).thenCompose(servers -> servers.stream()
.filter(server -> server.getPlayerCount() != null)
.filter(server -> server.getPlayerCount() < server.getMaxPlayers())
.min(Comparator
.comparingInt((Server server) -> server.getPlayerCount())
.thenComparingInt(Server::getNumericalId))
.>map(server -> {
String serverName = groupName + "-" + server.getNumericalId();
return player.connect(serverName)
.thenApply(RouteResult.ConnectionAttempted::new);
})
.orElseGet(() -> CompletableFuture.completedFuture(
new RouteResult.NoCapacity()
)));
}
public sealed interface RouteResult {
record NoCapacity() implements RouteResult {}
record ConnectionAttempted(
CloudPlayer.ConnectResult result
) implements RouteResult {}
}
}
```
`AVAILABLE` and `INGAME` servers can accept players. Sorting by player count spreads new connections across the group, while the numerical ID gives the selection a stable tie-breaker.
The server name uses SimpleCloud's default `-` registration pattern, such as `lobby-3`. If you changed the registration pattern, build the name with that same pattern here.
Handle `NoCapacity` by keeping the player in your queue or fallback lobby. For `ConnectionAttempted`, use the returned `ConnectResult` to confirm the connection or show an appropriate fallback.
## Next steps
* Use the [Groups API](/docs/en/developer/api/groups) to create and configure groups.
* Use the [event handling guide](/docs/en/developer/guides/event-handling) when your plugin should react as servers become available.
* See the [Servers API](/docs/en/developer/api/servers) for server queries, models, and lifecycle actions.
# Installation
Source: https://simplecloud.app/docs/en/developer/installation
Add the Cloud API to your Minecraft plugin
## Add the API dependency
The Cloud API requires Java 21. Add the SimpleCloud and Buf repositories, then add the API with `compileOnly` in Gradle or `provided` in Maven:
Do not shade the Cloud API into your plugin. The `simplecloud-api` platform plugin provides it at runtime, and bundling another copy can cause class-loading conflicts.
Pin the dependency to the version you tested before releasing your plugin.
## Require the platform plugin
Declare `simplecloud-api` as a required dependency so it loads before your plugin. SimpleCloud's default templates already include the matching platform plugin. If you use custom templates, keep it in the `plugins` directory.
Add the dependency to `src/main/resources/paper-plugin.yml`:
```yaml paper-plugin.yml theme={null}
name: my-plugin
version: "1.0.0"
main: com.example.MyPlugin
api-version: "1.21"
dependencies:
server:
simplecloud-api:
load: BEFORE
required: true
join-classpath: true
```
Add the dependency to `src/main/resources/plugin.yml`:
```yaml plugin.yml theme={null}
name: my-plugin
version: "1.0.0"
main: com.example.MyPlugin
api-version: "1.21"
folia-supported: true
depend:
- simplecloud-api
```
Add the dependency to `src/main/resources/plugin.yml`:
```yaml plugin.yml theme={null}
name: my-plugin
version: "1.0.0"
main: com.example.MyPlugin
api-version: "1.20"
depend:
- simplecloud-api
```
Add the dependency to the `@Plugin` annotation on your main class:
```java MyPlugin.java theme={null}
import com.velocitypowered.api.plugin.Dependency;
import com.velocitypowered.api.plugin.Plugin;
@Plugin(
id = "my-plugin",
name = "My Plugin",
version = "1.0.0",
dependencies = {@Dependency(id = "simplecloud-api")}
)
public final class MyPlugin {
}
```
Add the dependency to `src/main/resources/plugin.yml`:
```yaml plugin.yml theme={null}
name: my-plugin
version: "1.0.0"
main: com.example.MyPlugin
depends:
- simplecloud-api
```
## Create one client
Create a `CloudApi` instance when your plugin starts, reuse it for every request, and close it when your plugin stops. SimpleCloud provides the connection settings automatically.
```java MyPlugin.java theme={null}
package com.example;
import app.simplecloud.api.CloudApi;
import org.bukkit.plugin.java.JavaPlugin;
public final class MyPlugin extends JavaPlugin {
private CloudApi cloudApi;
@Override
public void onEnable() {
cloudApi = CloudApi.create();
}
@Override
public void onDisable() {
if (cloudApi != null) {
cloudApi.close();
}
}
}
```
Most API calls return `CompletableFuture`; compose them instead of blocking, and use your platform's scheduler before changing platform state from a callback.
### Velocity lifecycle
On Velocity, create and close the same client from the proxy lifecycle events:
```java MyPlugin.java theme={null}
private CloudApi cloudApi;
@Subscribe
public void onProxyInitialize(ProxyInitializeEvent event) {
cloudApi = CloudApi.create();
}
@Subscribe
public void onProxyShutdown(ProxyShutdownEvent event) {
if (cloudApi != null) {
cloudApi.close();
}
}
```
`CloudApi.create()` uses the connection settings supplied by SimpleCloud. If your plugin needs different request timeouts or cache behavior, pass a custom `CloudApiOptions` instance.
## Troubleshooting
Confirm that your build contains both repositories shown above, then refresh dependencies with `./gradlew --refresh-dependencies` or `mvn -U package`.
Check that:
* The matching `simplecloud-api` platform plugin is installed and enabled.
* Your plugin declares it as a required dependency. Paper plugins also need `join-classpath: true`.
* Your build uses `compileOnly` or `provided` and does not shade the API.
Confirm that SimpleCloud started the server and that the matching `simplecloud-api` platform plugin is enabled.
# Cloud API
Source: https://simplecloud.app/docs/en/developer/overview
Build Minecraft plugins that work with your SimpleCloud network
## Choose where to begin
Add the dependency and create a client for your plugin.
Create groups, change their configuration, and request new servers.
Find, inspect, update, and stop server instances.
Manage servers that keep their identity across restarts.
Look up players, send messages, and connect them to servers.
Run code when groups, servers, persistent servers, or blueprints change.
## Build a common workflow
Move an online player to another server and handle the result.
Select available capacity without competing with SimpleCloud autoscaling.
Subscribe to network changes for the lifetime of your plugin.
# Configurators
Source: https://simplecloud.app/docs/en/manual/configuration/configurators
Customize software configuration files before a server starts
## Create a custom configurator
The dashboard selects a built-in configurator when you create a group or persistent server. A standard setup needs no extra work.
Create a custom configurator when the built-in one does not manage a setting you need. Use [templates](/docs/en/manual/setup/templates) when you only need to copy the same files to your servers.
A custom configurator replaces the selected built-in configurator. Keep the built-in settings that your server needs, especially its port and proxy settings.
This example extends the **Paper/Spigot Standalone** configurator with a difficulty and view distance. If your server connects through a proxy, start with the matching proxy configurator instead.
On the serverhost, create `options/configurators/paper_survival.yml`:
```yaml options/configurators/paper_survival.yml theme={null}
paths:
- path: "server.properties"
type: "PROPERTIES"
data:
server-ip: "0.0.0.0"
server-port: %port%
max-players: %max-players%
online-mode: true
difficulty: "hard"
view-distance: 10
```
Each `path` is relative to the server's own directory. The file can contain several path entries when you need to configure more than one file.
Open the group or persistent server in the dashboard, then go to **Settings > Blueprint**. Under **Software Configuration**, select **Custom**, enter `paper_survival`, and save.
Restart the group or persistent server. SimpleCloud applies the configurator to every server that uses its blueprint before that server starts.
If the server can run on multiple serverhosts, add the configurator file to each one.
## Configurator reference
Each entry under `paths` identifies a configuration file, its format, and the values to apply.
| Type | File format |
| ------------ | --------------- |
| `YML` | YAML |
| `JSON` | JSON |
| `TOML` | TOML |
| `PROPERTIES` | Java properties |
| `TXT` | Plain text |
Structured files keep values that are not specified in the configurator. `TXT` replaces the complete file.
Use placeholders when a value depends on the server instance.
| Placeholder | Value |
| --------------------------- | ------------------------------- |
| `%port%` | Assigned port |
| `%group%` | Group or persistent server name |
| `%numerical-id%` | Instance number |
| `%type%` | Server or proxy type |
| `%min-memory%` | Minimum memory in MB |
| `%max-memory%` | Maximum memory in MB |
| `%max-players%` | Player limit |
| `%forwarding-secret%` | Proxy forwarding secret |
| `%velocity-config-version%` | Velocity configuration version |
Quote placeholders whose resulting value must be text:
```yaml theme={null}
server-name: "%group%"
server-port: %port%
```
Custom properties from the group or persistent server are also available as placeholders. For example, a property named `motd` can be used as `%motd%`.
To insert a password, token, or another private value, use a [secret reference](/docs/en/manual/configuration/secrets) as the Configurator value:
```yaml theme={null}
password: "{{ secrets.DATABASE_PASSWORD }}"
```
## Troubleshooting
Confirm that `options/configurators/{name}.yml` exists on every serverhost that can run the server. The custom name in the dashboard must match the filename without `.yml`.
Restart the server first. If the value still does not change, check that `path` is relative to the server directory, `type` matches the file format, and the setting is nested correctly under `data`.
Check the placeholder spelling and use percent syntax such as `%port%`. For a custom placeholder, add a property with the same name to the group or persistent server.
Check the serverhost log for a configurator error. Common causes are invalid YAML, an unsupported `type`, or a value whose structure does not match the target file.
# Secrets
Source: https://simplecloud.app/docs/en/manual/configuration/secrets
Keep passwords and tokens out of templates and workflow files
## Use a database password in a plugin configuration
This example uses a template. SimpleCloud leaves the reference in the template and inserts the password into the running server's copy before the process starts.
Open **[Settings > Secrets](https://dash.simplecloud.app/redirect?target=%2Fsettings%2Fsecrets)** in the dashboard and select **Add secret**. Enter `DATABASE_PASSWORD` as the key, enter the password as the value, then select **Encrypt & save**.
At least one serverhost must be connected before you can add a secret. After saving, the dashboard shows the key but cannot display the value again.
Open **Files**, select the serverhost, and edit the plugin configuration in the matching [template](/docs/en/manual/setup/templates). For example, place this file at `templates/lobby/plugins/DatabasePlugin/config.yml`:
```yaml templates/lobby/plugins/DatabasePlugin/config.yml theme={null}
database:
host: "db.internal.example"
port: 3306
name: "minecraft"
username: "simplecloud"
password: "{{ secrets.DATABASE_PASSWORD }}"
```
Adapt the path and surrounding settings to your plugin. Keep the secret reference exactly as shown.
For a persistent server that already has this file, stop the server and edit its existing configuration from the server's **Files** page instead. A template does not replace an existing persistent-server file.
Start a new `lobby` server. If you edited a persistent server, start it again. SimpleCloud copies the template when needed, replaces the reference in the running file, and then starts the server process.
Servers that are already running keep the value with which they started.
Confirm that the plugin connects successfully. When you open the running file in the dashboard, the editor still shows `{{ secrets.DATABASE_PASSWORD }}` instead of the password. This is intentional.
## Use secrets in configurators and workflows
The same `{{ secrets.KEY }}` reference works in a [Configurator](/docs/en/manual/configuration/configurators). Use it as a value, not as part of the target file path:
```yaml theme={null}
paths:
- path: "plugins/DatabasePlugin/config.yml"
type: "YML"
data:
database:
password: "{{ secrets.DATABASE_PASSWORD }}"
```
Workflow parameters can also use secrets. This upload step reads its bearer token at runtime, so the token does not appear in the [workflow file](/docs/en/manual/configuration/workflows):
```yaml theme={null}
- name: upload-backup
uses: simplecloud/upload
with:
from: "{{ runtime.server-dir }}/backups/latest.zip"
to: "https://backups.example.com/upload"
method: "PUT"
authorization-bearer: "{{ secrets.BACKUP_TOKEN }}"
```
Create `BACKUP_TOKEN` under **Settings > Secrets** before running this workflow. The upload source must already exist.
## Rotate or delete a secret
Open the action menu next to a key under **Settings > Secrets** and select **Rotate secret** to replace its value. The key stays the same, so you do not need to edit its references.
Restart each affected server to apply the new value. During a rolling restart, old and new instances can temporarily use different values.
Remove every reference before deleting a secret. A server does not start if one of its configuration files requires a missing secret. A workflow that uses a missing secret cannot receive its value.
SimpleCloud creates and manages `VELOCITY_SECRET` for secure proxy forwarding. Do not rotate or delete it manually. A changed forwarding secret must reach the proxy and every backend server together, or connections between them will fail.
## How secrets are protected
Every serverhost in the network can use every key. Use separate networks when values must not be shared between hosts.
When you save a secret, the dashboard encrypts it in your browser with the network's public key. The controller stores the encrypted value and cannot decrypt it. The connected serverhosts share the corresponding private key and decrypt secrets in memory when a server or workflow needs them.
During server startup, SimpleCloud runs the configured start workflows first. It then replaces secret references in copied or configured text files and starts the server process.
The source template keeps its reference. SimpleCloud records only the managed file locations, not the secret values. That record lets later rotations update the same locations.
The running server needs the real value, so SimpleCloud writes it to the running configuration file. Users and processes with direct access to that serverhost or server directory can read it.
Secrets keep the value out of templates and workflow files. The controller stores only ciphertext, but the software using the secret receives the real value.
Secret keys and values have these limits:
* A key starts with a letter or underscore and contains up to 64 letters, numbers, underscores, or hyphens. The dashboard converts new keys to uppercase.
* A value cannot be empty and can contain up to 16 KB. Whitespace and line breaks are preserved.
* References are case-sensitive. Copy the reference shown under **Settings > Secrets** to avoid a mismatch.
* Use references in text configuration files. Do not put them in JAR files, worlds, databases, or archives.
## Troubleshooting
Start or reconnect a serverhost. The first connected serverhost registers the network's encryption key, after which the dashboard enables secret creation.
Open **Settings > Secrets** and compare the key with the text inside `{{ secrets.KEY }}`. Keys are case-sensitive. Add the missing key or correct the reference before starting the server.
Rotation does not change a process that is already running. Restart every server and rerun every manual workflow that should use the new value.
The dashboard file editor and downloads replace managed plaintext with the reference before sending the file to your browser. Check the application behavior or its connection result instead of looking for the value in the editor.
Check the serverhost log for `Missing secret` or `Failed to apply secrets`. Create the named key or remove its reference, then start the server again. If one required secret is missing, SimpleCloud leaves all secret-managed files unchanged.
# Workflows
Source: https://simplecloud.app/docs/en/manual/configuration/workflows
Run file operations when a server starts, stops, or on demand
## Run the backup workflow
Create `workflows/default/backup.yml` in your serverhost directory:
```yaml workflows/default/backup.yml theme={null}
name: Backup Workflow
steps:
- name: copy-running-to-backup
uses: simplecloud/copy
with:
from: "{{ runtime.server-dir }}"
to: "{{ runtime.templates }}/.backup/{{ runtime.name }}/{{ time.now.date }}/{{ time.now.dateTime }}-{{ runtime.nice-id }}-{{ runtime.process-id }}"
init-dir-if-missing: true
```
Restart the serverhost. SimpleCloud uses the file path as the workflow ID, so this workflow becomes `default/backup`.
In the dashboard, open a server group or persistent server and go to **Settings > Workflows**. Under **Manual Workflows**, add `default/backup`.
Start the server if it is not already running. Then open its actions menu and run `default/backup` to test the workflow.
On the serverhost, open:
```text theme={null}
templates/.backup///--/
```
Confirm that the final directory contains the files you expected. Its timestamp and process ID keep separate backup runs apart.
A workflow is available only on serverhosts that contain its file. If the affected servers can run on multiple serverhosts, add the same file to each one and restart them.
The manual action copies files while the Minecraft server is running. Files that change during the copy, such as worlds and plugin data, may not form a consistent backup.
For those files, add `default/backup` under **On Stop Workflows** and stop the server normally. Stop workflows run after the server process exits.
Place `default/backup` before `internal/cleanup`.
`internal/cleanup` removes a group server's running directory. Any workflow that reads that directory must run before cleanup.
This workflow creates file copies but does not test restores or remove old backups. Verify that you can restore the data you need and manage retention for `templates/.backup/`.
## Understand the workflow file
The backup workflow contains the same basic structure as every workflow:
* `name` identifies the workflow in serverhost logs.
* `steps` contains the operations in the order they run.
* `name` inside a step identifies that step in logs.
* `uses` selects the action. This workflow uses `simplecloud/copy`.
* `with` contains the values required by the action.
In this workflow, `from` points to the running server directory and `to` builds a unique backup path. If the source is missing, `init-dir-if-missing: true` creates an empty source directory instead of failing. Always verify that the resulting backup contains the expected files.
### Values used by the workflow
Values inside `{{ ... }}` are replaced when the workflow runs.
| Value | Result |
| -------------------------- | -------------------------------------- |
| `{{ runtime.server-dir }}` | Running server directory |
| `{{ runtime.templates }}` | Serverhost template directory |
| `{{ runtime.name }}` | Server group or persistent server name |
| `{{ runtime.nice-id }}` | Running server name, such as `lobby-1` |
| `{{ runtime.process-id }}` | Running process ID |
| `{{ time.now.date }}` | Current date |
| `{{ time.now.dateTime }}` | Current date and time |
## Adapt the backup workflow
Use the backup workflow as a starting point:
Copy `workflows/default/backup.yml` to a new path, such as `workflows/custom/world-backup.yml`.
Give it a new `name`, then change the copy paths and exclusions for your task.
Restart every serverhost that contains the new file.
Add `custom/world-backup` under **Settings > Workflows**. A workflow ID is always its path below `workflows/`, without `.yml`.
### Change what gets copied
The `simplecloud/copy` action accepts these settings under `with`:
| Setting | Purpose |
| --------------------- | ---------------------------------------------------------------------------------- |
| `from` | File or directory to copy |
| `to` | Destination for the copy |
| `replace` | Whether to overwrite existing files; defaults to `true` |
| `exclude` | Path or list of paths to leave out |
| `init-dir-if-missing` | Whether to create the source directory when it does not exist; defaults to `false` |
For example, add an `exclude` list to skip logs and caches while keeping the rest of the backup unchanged:
```yaml theme={null}
with:
from: "{{ runtime.server-dir }}"
to: "{{ runtime.templates }}/.backup/{{ runtime.name }}/{{ time.now.date }}/{{ time.now.dateTime }}-{{ runtime.nice-id }}-{{ runtime.process-id }}"
init-dir-if-missing: true
exclude:
- "logs/**"
- "cache/**"
```
Patterns in `exclude` are relative to `from`.
## Available actions
`simplecloud/copy` copies a file or directory from `from` to `to`. Use `replace` to control whether existing files are overwritten and `exclude` to skip matching paths.
`simplecloud/compress` creates an archive and `simplecloud/decompress` extracts one. Both require `from` and `to`; `replace` is optional. The archive filename determines its format.
`simplecloud/upload` sends the file in `from` to the URL in `to`. It uploads files, not directories. You can also set the HTTP `method` and an `authorization-bearer` value.
Store long-lived access tokens under **Settings > Secrets** and set `authorization-bearer` to a [secret reference](/docs/en/manual/configuration/secrets), such as `"{{ secrets.BACKUP_TOKEN }}"`.
`simplecloud/delete` removes the configured `path`. Use `min-age`, such as `7d`, to keep newer files.
Delete paths are not limited to the server directory. Check the final path before running the workflow.
`simplecloud/foreach` runs nested steps for each entry in `items`. Set `as` to the variable name used by the nested `steps`.
## Built-in workflows
| Workflow | Purpose |
| ------------------ | -------------------------------------------- |
| `internal/setup` | Prepares the server directory before startup |
| `internal/cleanup` | Cleans up files after the server stops |
Keep `internal/setup` and `internal/cleanup` assigned unless you intentionally replace their behavior.
## Troubleshooting
Workflow IDs are entered manually in the dashboard. Confirm the file exists on the serverhost, restart the serverhost, and add the ID again.
Check that the ID matches the file path. For example, `custom/world-backup` must point to `workflows/custom/world-backup.yml`.
Check the serverhost logs for `Backup Workflow` and `copy-running-to-backup`. For an automatic backup, also confirm that `default/backup` comes before `internal/cleanup`.
# CLI
Source: https://simplecloud.app/docs/en/manual/introduction/architecture/cli
Set up and manage SimpleCloud from your terminal
## Install the CLI
Run the installer on the machine that will host SimpleCloud:
```bash theme={null}
curl -fsSL https://get.simplecloud.app | bash
```
Then check that the CLI is available:
```bash theme={null}
sc --version
```
To set up the first serverhost from the dashboard, follow [Installation](/docs/en/manual/setup/installation). To complete the setup from the CLI, continue below.
## Set up your serverhost
Start the setup wizard:
```bash theme={null}
sc setup
```
The wizard signs you in, connects the machine to your network, and installs the serverhost. When it finishes, you can manage SimpleCloud from the CLI or dashboard.
## Manage SimpleCloud on this machine
Use these commands to operate the local installation:
| Task | Command |
| --------------------------- | ---------------------- |
| Start SimpleCloud | `sc start` |
| Stop SimpleCloud | `sc stop` |
| Restart SimpleCloud | `sc restart` |
| Check its status | `sc status` |
| View serverhost logs | `sc logs serverhost` |
| Open the serverhost console | `sc attach serverhost` |
Local commands such as `sc start` manage SimpleCloud on the current machine. Commands under `sc server` manage Minecraft servers in your network.
## Manage groups and servers
Create a server group with the interactive wizard:
```bash theme={null}
sc group create
```
You can then start a server and view the running servers:
```bash theme={null}
sc group start lobby
sc server list
```
Use these commands for common server tasks:
```bash theme={null}
sc server info lobby 1
sc server logs lobby 1 --follow
sc server stop lobby 1
```
See [Server groups](/docs/en/manual/setup/server-groups) and [Servers](/docs/en/manual/setup/servers) for the complete workflows.
## Update SimpleCloud
Upgrade the CLI and installed SimpleCloud components with one command:
```bash theme={null}
sc upgrade
```
If an installed component needs to be downloaded again, run:
```bash theme={null}
sc repair
```
## Sign in
Run `sc login` when you need to sign in again. Use `sc whoami` to check the current account and `sc logout` to sign out.
## Switch between networks
The CLI saves each network as a context and sends network commands to the active one. Setup creates your first context automatically.
```bash theme={null}
sc context list
sc context use
```
Run `sc context add` to connect the CLI to another network.
## Add another serverhost
On the new machine, install the CLI and run:
```bash theme={null}
sc serverhost add
```
Follow [Multi-root setup](/docs/en/manual/setup/multi-root) for the complete process.
## Discover more commands
The CLI also supports templates, persistent servers, multiple contexts, and advanced installation options. These workflows have their own guides, while the CLI's built-in help always shows the current command syntax:
```bash theme={null}
sc --help
sc group --help
sc server --help
sc persistent-server --help
```
Learn more in [Templates](/docs/en/manual/setup/templates) and [Persistent servers](/docs/en/manual/setup/persistent-servers).
# Architecture
Source: https://simplecloud.app/docs/en/manual/introduction/architecture/overview
Understand how the dashboard, CLI, controller, and serverhost work together
## The three parts you use
The web interface for configuring your network and viewing servers, logs, and status.
The terminal interface for setting up serverhosts and managing the same network without the dashboard.
The background service that prepares and runs Minecraft servers on its machine.
The hosted controller coordinates these parts and stores the network state. You do not install or operate it yourself.
## How they work together
1. Install a serverhost on every machine whose resources you want SimpleCloud to use.
2. Configure groups and persistent servers in the dashboard or CLI.
3. SimpleCloud starts the requested Minecraft servers on a suitable serverhost and reports their status and logs.
The dashboard and CLI change the same network, so choose whichever interface fits the task. The serverhost does not replace either interface. It runs the Minecraft servers you configure through them.
When you add another machine, install another serverhost. SimpleCloud can then use both machines to run your network.
## Next steps
Connect your first machine and start using the dashboard.
Run replaceable server instances from shared settings and files.
Run one named server that keeps its files across restarts.
# Serverhost
Source: https://simplecloud.app/docs/en/manual/introduction/architecture/serverhost
Connect a machine that SimpleCloud can use to run Minecraft servers
## What a serverhost does
A serverhost is a machine that runs Minecraft servers for your SimpleCloud network. Install one on each machine whose CPU and memory you want SimpleCloud to use.
The serverhost runs in the background. You manage Minecraft servers and choose which serverhosts may run them through the dashboard.
A serverhost:
* Prepares Minecraft server files from your templates
* Starts and stops Minecraft servers
* Applies the software, plugins, memory, and other settings you configure
* Sends server status, logs, and resource usage to SimpleCloud
## Add a serverhost
In the dashboard, open **Settings > Server Hosts** and select **Add Host**. Configure the host, then run the generated setup command on the machine you want to add.
The command installs SimpleCloud, connects the serverhost to your network, and starts it. For prerequisites and the complete setup process, follow the [installation guide](/docs/en/manual/setup/installation).
Use **Settings > Server Hosts** to view and change a host's settings. Choose which hosts may run servers when you configure a server group.
## Check or control a serverhost
Use the CLI when you need to start, stop, update, or troubleshoot the serverhost itself.
Run these commands from the SimpleCloud installation directory:
```bash theme={null}
# Show whether the serverhost is running
sc status serverhost
# Read recent serverhost logs
sc logs serverhost --lines 200
# Start or stop the serverhost
sc start serverhost
sc stop serverhost
# Restart it and install an available update
sc restart serverhost --update
```
### What happens to running Minecraft servers
When you stop or restart a serverhost, the CLI asks whether it should also stop the Minecraft servers running on that machine.
* Choose **Yes** when taking the machine offline or when the Minecraft servers must stop too.
* Choose **No** for short serverhost maintenance if the Minecraft servers should remain online. The serverhost reconnects to them after it starts again.
Do not shut down or reboot the machine while Minecraft servers are still running. Stop them first so they can save their data cleanly.
## Troubleshoot a serverhost
If a serverhost is offline or a server cannot start, check that:
* The serverhost is online.
* It has enough free memory for the server.
* The required Java version is installed.
* The group is allowed to use that serverhost.
Use `sc logs serverhost --lines 200` for more information. You can also review the affected Minecraft server's logs in the dashboard.
## Use multiple serverhosts
With multiple serverhosts, SimpleCloud can distribute servers across the machines allowed by each group. This adds capacity, but the machines do not share a filesystem.
* Keep templates, workflows, and configurator files synchronized so a server can start correctly on any eligible host.
* While a server is running, its files and logs exist only on the serverhost that started it.
* A persistent server's files stay on its assigned serverhost. Changing its serverhost does not move those files.
Follow the [multi-root setup guide](/docs/en/manual/setup/multi-root) to add another machine and synchronize the shared files.
## Related pages
* [Templates](/docs/en/manual/setup/templates) explains how server files are prepared.
* [Configurators](/docs/en/manual/configuration/configurators) explains automatic configuration changes.
* [Workflows](/docs/en/manual/configuration/workflows) explains advanced preparation and cleanup steps.
# FAQ
Source: https://simplecloud.app/docs/en/manual/introduction/faq
Answers to common questions about setting up and using SimpleCloud
SimpleCloud helps you set up and manage a Minecraft server network from one
dashboard or the `sc` command.
Read the [SimpleCloud overview](/docs/en/manual/introduction/overview) to learn how
it organizes your network.
Start with the [installation guide](/docs/en/manual/setup/installation). It takes
you from signing in to the dashboard to connecting your first serverhost.
Use a **server group** when every server should share the same setup and its
local files do not need to survive replacement. Groups work well for
lobbies, minigames, and proxies.
Use a **persistent server** for one named server that keeps its files, such
as an SMP, Skyblock, or build server.
Compare the options in [Server groups](/docs/en/manual/setup/server-groups) and
[Persistent servers](/docs/en/manual/setup/persistent-servers).
Your serverhost can run on Linux or macOS. Linux is recommended for
production, while macOS is useful for local testing. Windows serverhosts are
not supported yet.
You can use the web dashboard from a different device.
See the [installation guide](/docs/en/manual/setup/installation) for the system
requirements.
Choose one of the software options offered by the dashboard. If it is not listed,
choose **Custom** and fill in the required fields.
Follow the creation steps for a [server group](/docs/en/manual/setup/server-groups#create-a-server-group)
or a [persistent server](/docs/en/manual/setup/persistent-servers#create-a-persistent-server).
Basic setup does not require advanced technical knowledge. You should be
comfortable opening a terminal and running the command provided by the
dashboard. More advanced customization may require familiarity with your
Minecraft server software.
Join the [SimpleCloud Discord](https://discord.simplecloud.app) for community
help.
# Overview
Source: https://simplecloud.app/docs/en/manual/introduction/overview
Run and manage your Minecraft server network from one dashboard or the SimpleCloud CLI
## Get started
Open the SimpleCloud Dashboard and sign in. Its setup wizard gives you the command that installs SimpleCloud on your first machine and connects it to your network.
Connect your first machine and create your first server.
## Choose how your servers work
* A **server group** creates replaceable servers from shared settings and files. Use groups for proxies, lobbies, and game modes that may need multiple identical servers or automatic scaling.
* A **persistent server** is one named server that keeps its own world and files. Use it for a long-running server such as an SMP or build server.
* A **serverhost** is a machine on which SimpleCloud runs your Minecraft servers. Add another serverhost when you want to use another machine.
## Learn the essentials
Create servers that share a configuration.
Create a server that keeps its world and files.
Manage and monitor your network in the browser.
Manage your network from the terminal.
# Philosophy
Source: https://simplecloud.app/docs/en/manual/introduction/philosophy
The principles and values that guide how we build SimpleCloud
## Who we are
We are not a company. We are a group of Minecraft enthusiasts building SimpleCloud together in our free time. These principles guide our decisions across the product.
## Guiding principles
### Simplicity takes effort
Making SimpleCloud simple to use requires work behind the scenes. We hide unnecessary complexity behind clear interfaces and ask whether a server administrator can understand a feature without first learning how its internals work.
### User experience comes first
Before we build a feature, we ask how a server administrator would naturally use it. This sometimes means choosing a practical workflow over a technically elegant one. If a feature works but is confusing, we improve the feature instead of expecting users to work around it.
### Continuous improvement
We do more than add features. We revisit existing workflows, fix problems, and use community feedback to decide what needs attention. We prefer improving the product over documenting avoidable workarounds.
### Built by volunteers
SimpleCloud is developed by volunteers in their free time. We build what we believe in, without commercial pressure or investor deadlines. This lets us focus on quality and give features the time they need.
We are not bound by deadlines or feature checklists. If something needs more work, it gets more work.
### The brand matters to us
SimpleCloud is a Minecraft project, but we still care about creating a cohesive brand. Its visual identity is part of what makes the project enjoyable for us, and we treat it with the same care as the product itself.
## What this means for you
* Features ship when they are ready, not because a roadmap deadline arrived.
* Fixing problems takes priority over adding features for their own sake.
* Community feedback helps shape the direction of SimpleCloud.
* We write documentation that we would want to use ourselves.
# Sponsors
Source: https://simplecloud.app/docs/en/manual/introduction/sponsors
Organizations that support SimpleCloud and its open-source development
Depot supports SimpleCloud through its OSS Sponsorship Program by providing access to Depot CI. This gives our team faster build and caching infrastructure for our CI workflows.
Mintlify supports SimpleCloud through its open-source program by providing the documentation platform and hosting behind this site. This helps us make SimpleCloud easier to learn and use.
We are grateful to Depot and Mintlify for supporting SimpleCloud and open-source software.
# Updates
Source: https://simplecloud.app/docs/en/manual/introduction/updates
Keep the SimpleCloud CLI and serverhost up to date
## Update the CLI
The CLI tells you when a new version is available but does not update automatically. To install the latest release, run:
```bash theme={null}
sc upgrade cli
```
The command replaces the CLI with the latest release. It does not restart the serverhost or any Minecraft servers.
Run `sc --version` afterward to confirm the installed version.
## Automatic serverhost updates
SimpleCloud automatically assigns the latest release to each serverhost. When the assigned version differs from the installed version, the serverhost downloads the update and restarts itself.
The restart affects only the serverhost process. Minecraft servers keep running because they use separate processes.
Automatic updates do not update the CLI, Minecraft server software, or plugins. Update those separately.
## Update the serverhost now
You normally do not need to update the serverhost yourself. To install an available update immediately, run this command from your SimpleCloud installation directory:
```bash theme={null}
sc restart --update
```
This command updates and restarts the serverhost. Run it during a maintenance window. SimpleCloud asks whether it should also stop the Minecraft servers running on this serverhost, unless you saved this choice earlier.
After the command completes, confirm that the serverhost is running:
```bash theme={null}
sc status serverhost
```
If the serverhost does not start, inspect its logs:
```bash theme={null}
sc logs serverhost
```
Fix the reported problem, then run `sc start serverhost` to start it again.
## Other update options
Use `sc upgrade` to update the CLI and all installed SimpleCloud components, or `sc upgrade serverhost` to download only the serverhost update.
```bash theme={null}
sc upgrade
sc upgrade serverhost
```
These commands do not restart running components. Restart the serverhost when you are ready to use its new version.
To test or roll back a release, download the version you want:
```bash theme={null}
sc upgrade serverhost@
```
The command does not restart the serverhost. Run `sc restart serverhost` when you are ready to use the selected version.
If the CLI installation is not writable by your user, run `sudo sc upgrade cli`. If the installation is damaged but already current, reinstall it with:
```bash theme={null}
sc upgrade cli --cli-force
```
When the CLI is several releases behind, it may require an update before other commands can run.
# Cloud Command
Source: https://simplecloud.app/docs/en/manual/plugin/cloud-command
Use SimpleCloud's in-game proxy commands for groups, servers, and players
## Supported software
| Software | Plugin Support |
| ---------- | -------------- |
| Velocity | Yes |
| BungeeCord | Yes |
| Gate | Planned |
## Install the plugin
Download Cloud Command from [GitHub](https://github.com/simplecloudapp/command-plugin/releases) and place it in the proxy template's `plugins/` folder. Standard SimpleCloud templates already include `simplecloud-api`; add it through the target's **Plugins** setting or the CLI if you use a custom template.
Start a matching proxy once. Cloud Command creates `plugins/simplecloud-command/messages.yml` in the running proxy directory.
For a group proxy, copy `plugins/simplecloud-command/messages.yml` from the running proxy to the same path in its template before stopping it. Files left only in a temporary proxy directory disappear when that proxy stops.
See [Templates](/docs/en/manual/setup/templates) for the complete workflow.
Give yourself `simplecloud.command.use`, join through the proxy, and run `/cloud`.
The help menu lists the subcommands you have permission to use.
## Commands
The root command is available as `/cloud`, `/sc`, and `/simplecloud`.
### Groups
| Command | Description |
| ------------------------------------ | --------------------------------------------------------------- |
| `/cloud group list` | List all groups |
| `/cloud group info ` | Show group type, memory, player limit, and running server count |
| `/cloud group start [count]` | Request one or more new servers for a group |
| `/cloud group stop [id]` | Stop all running servers in a group, or one numerical ID |
### Servers
| Command | Description |
| --------------------------------- | -------------------------------------------------- |
| `/cloud server list [group]` | List running servers, optionally filtered by group |
| `/cloud server info ` | Show state, memory, and players for one server |
| `/cloud server start ` | Request one new server for a group |
| `/cloud server stop ` | Stop one running server |
### Players
Use `group` for a server group target and `ps` for a persistent server target.
| Command | Description |
| ------------------------------------------------------ | ----------------------------------------------- |
| `/cloud player list ` | List players on a group or persistent server |
| `/cloud player info ` | Show player connection details |
| `/cloud player send ` | Send one player to a target |
| `/cloud player sendall ` | Send every online player to a target |
| `/cloud player sendfrom ` | Send players from one source server to a target |
| `/cloud player message ` | Send a plain text message to a player |
### Reload
| Command | Description |
| --------------- | --------------------------------------- |
| `/cloud reload` | Run the command plugin's reload command |
`/cloud reload` rereads `plugins/simplecloud-command/messages.yml` from the running proxy. Restart the proxy if you edited the template copy instead.
## Permissions
| Permission | Description |
| ------------------------------------ | --------------------------------------------------- |
| `simplecloud.command.use` | Use the root command and view available subcommands |
| `simplecloud.command.group.list` | Use `/cloud group list` |
| `simplecloud.command.group.info` | Use `/cloud group info` |
| `simplecloud.command.group.start` | Use `/cloud group start` |
| `simplecloud.command.group.stop` | Use `/cloud group stop` |
| `simplecloud.command.server.list` | Use `/cloud server list` |
| `simplecloud.command.server.info` | Use `/cloud server info` |
| `simplecloud.command.server.start` | Use `/cloud server start` |
| `simplecloud.command.server.stop` | Use `/cloud server stop` |
| `simplecloud.command.player.list` | Use `/cloud player list` |
| `simplecloud.command.player.info` | Use `/cloud player info` |
| `simplecloud.command.player.send` | Use player transfer commands |
| `simplecloud.command.player.message` | Use `/cloud player message` |
| `simplecloud.command.reload` | Use `/cloud reload` |
The help menu only shows commands for permissions the sender has.
## Troubleshooting
Confirm that `simplecloud-api` is installed and enabled on the same proxy. Cloud Command declares it as a required dependency.
Grant the matching permission. The help menu hides subcommands the sender cannot use.
Edit `plugins/simplecloud-command/messages.yml` in the proxy template, or copy the tested file back to the template before a temporary group proxy stops.
# Notify
Source: https://simplecloud.app/docs/en/manual/plugin/notify
Send server and group state notifications to staff across your proxy network
## Supported software
| Software | Plugin Support |
| ---------- | -------------- |
| Velocity | Yes |
| BungeeCord | Yes |
## Install the plugin
Download Notify from [GitHub](https://github.com/simplecloudapp/notify-plugin/releases) and place it in the proxy template's `plugins/` folder. Standard SimpleCloud templates already include `simplecloud-api`; add it through the target's **Plugins** setting or the CLI if you use a custom template.
Start a matching proxy once. Notify creates `plugins/simplecloud-notify/messages.yml` in the running proxy directory.
For a group proxy, copy `plugins/simplecloud-notify/messages.yml` from the running proxy to the same path in its template before stopping it. Changes that exist only in a temporary running directory disappear when that proxy stops.
See [Templates](/docs/en/manual/setup/templates) for the complete workflow.
Run `/scnotify reload config` after editing the file on a running proxy. If you edited the template copy, restart the proxy instead.
A successful reload prints `Notify configuration was reloaded.`
## Notifications
Notify subscribes to the Cloud API event stream and can send messages for:
* Server state changes to `STARTING`, `AVAILABLE`, and `STOPPING`
* Server stopped events
* Group created events
* Group deleted events
Set a notification message to `null` to disable that specific notification. Set the whole `notifications.server` or `notifications.group` section to `null` to disable that category.
Staff can also disable notifications for themselves with `/scnotify disable` and turn them back on with `/scnotify enable`. Notify stores this choice in the player's SimpleCloud properties, so it follows the player across proxies. Notifications are enabled by default.
## Configuration
The generated `messages.yml` contains message text, reusable variables, and formatting options. Notify uses [MiniMessage syntax](https://docs.papermc.io/adventure/minimessage/) for text formatting.
```yaml theme={null}
version: "1"
format:
date: "dd.MM.yyyy HH:mm:ss"
variables:
prefix: "⚡"
notifications:
hover:
server: |-
<#E2E8F0>Server information
<#94A3B8>Time<#475569>: <#E2E8F0>