Repository: dirien/minectl
Branch: main
Commit: 9fcd00bc85ce
Files: 163
Total size: 553.7 KB
Directory structure:
gitextract_l55wna43/
├── .dockerignore
├── .github/
│ ├── CODEOWNERS
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug.yaml
│ │ ├── config.yml
│ │ └── feature.yaml
│ ├── PULL_REQUEST_TEMPLATE.md
│ ├── dependabot.yaml
│ └── workflows/
│ ├── ci.yaml
│ ├── lock.yml
│ └── ossf-scorecard-action.yaml
├── .gitignore
├── .golangci.yaml
├── .goreleaser.yaml
├── .pre-commit-config.yaml
├── AGENTS.md
├── CONTRIBUTING.md
├── DCO
├── Dockerfile
├── LICENSE
├── Makefile
├── README.md
├── SECURITY.md
├── artifacthub-repo.yml
├── cmd/
│ └── minectl/
│ ├── AGENTS.md
│ ├── create.go
│ ├── delete.go
│ ├── list.go
│ ├── minectl.go
│ ├── plugins.go
│ ├── rcon.go
│ ├── update.go
│ └── wizard.go
├── config/
│ ├── bedrock/
│ │ ├── server-akamai.yaml
│ │ ├── server-aws.yaml
│ │ ├── server-civo.yaml
│ │ ├── server-do.yaml
│ │ ├── server-exoscale.yaml
│ │ ├── server-gce.yaml
│ │ ├── server-hetzner.yaml
│ │ ├── server-oci.yaml
│ │ ├── server-ovh.yaml
│ │ ├── server-scaleway.yaml
│ │ └── server-vexxhost.yaml
│ ├── bungeecord/
│ │ ├── proxy-civo.yaml
│ │ ├── proxy-do.yaml
│ │ └── proxy-vultr.yaml
│ ├── craftbukkit/
│ │ ├── server-akamai.yaml
│ │ └── server-do.yaml
│ ├── fabric/
│ │ ├── server-akamai.yaml
│ │ ├── server-civo.yaml
│ │ └── server-do.yaml
│ ├── forge/
│ │ ├── server-akamai.yaml
│ │ ├── server-civo.yaml
│ │ └── server-do.yaml
│ ├── java/
│ │ ├── server-akamai.yaml
│ │ ├── server-aws-arm.yaml
│ │ ├── server-aws-spot.yaml
│ │ ├── server-aws.yaml
│ │ ├── server-azure-spot.yaml
│ │ ├── server-azure.yaml
│ │ ├── server-civo.yaml
│ │ ├── server-do.yaml
│ │ ├── server-exoscale.yaml
│ │ ├── server-fuga.yaml
│ │ ├── server-gce-arm.yaml
│ │ ├── server-gce-spot.yaml
│ │ ├── server-gce.yaml
│ │ ├── server-hetzner-arm.yaml
│ │ ├── server-hetzner.yaml
│ │ ├── server-oci.yaml
│ │ ├── server-ovh.yaml
│ │ ├── server-scaleway.yaml
│ │ ├── server-vexxhost.yaml
│ │ └── server-vultr.yaml
│ ├── multipass/
│ │ ├── server-java.yaml
│ │ └── server-papermc.yaml
│ ├── nukkit/
│ │ ├── server-azure.yaml
│ │ ├── server-civo.yaml
│ │ ├── server-do.yaml
│ │ ├── server-fuga.yaml
│ │ ├── server-gce.yaml
│ │ └── server-ovh.yaml
│ ├── papermc/
│ │ ├── server-akamai.yaml
│ │ ├── server-aws-arm.yaml
│ │ ├── server-aws.yaml
│ │ ├── server-azure-arm.yaml
│ │ ├── server-azure.yaml
│ │ ├── server-civo.yaml
│ │ ├── server-do.yaml
│ │ ├── server-exoscale.yaml
│ │ ├── server-fuga.yaml
│ │ ├── server-gce-arm.yaml
│ │ ├── server-hetzner.yaml
│ │ ├── server-oci-arm.yaml
│ │ ├── server-oci.yaml
│ │ ├── server-scaleway.yaml
│ │ ├── server-vexxhost.yaml
│ │ └── server-vultr.yaml
│ ├── powernukkit/
│ │ ├── server-azure.yaml
│ │ └── server-civo.yaml
│ ├── purpur/
│ │ ├── server-akamai.yaml
│ │ ├── server-aws-arm.yaml
│ │ ├── server-aws.yaml
│ │ ├── server-azure-arm.yaml
│ │ ├── server-azure.yaml
│ │ ├── server-civo.yaml
│ │ ├── server-do.yaml
│ │ ├── server-exoscale.yaml
│ │ ├── server-fuga.yaml
│ │ ├── server-gce-arm.yaml
│ │ ├── server-hetzner.yaml
│ │ ├── server-oci-arm.yaml
│ │ ├── server-oci.yaml
│ │ ├── server-scaleway.yaml
│ │ ├── server-vexxhost.yaml
│ │ └── server-vultr.yaml
│ ├── spigot/
│ │ ├── server-akamai.yaml
│ │ ├── server-azure.yaml
│ │ └── server-do.yaml
│ ├── velocity/
│ │ ├── proxy-do.yaml
│ │ └── proxy-gce.yaml
│ └── waterfall/
│ ├── proxy-azure.yaml
│ ├── proxy-do.yaml
│ └── proxy-vultr.yaml
├── development.md
├── docs/
│ ├── architecture.md
│ ├── authentication.md
│ ├── cli-reference.md
│ ├── colored-motd.md
│ ├── configuration.md
│ ├── dashboard/
│ │ └── tutorial.json
│ ├── editions.md
│ ├── features.md
│ ├── getting-started-civo-bedrock.md
│ ├── getting-started-civo.md
│ ├── getting-started-exoscale.md
│ ├── getting-started-gce.md
│ ├── getting-started-scaleway.md
│ ├── minectl.drawio
│ ├── multi-server-monitoring-civo.md
│ ├── running-minecraft-luckyblocks-budget-scaleway.md
│ └── skyblock-papermc-hetzner.md
├── go.mod
├── go.sum
├── internal/
│ ├── logging/
│ │ └── logging.go
│ ├── manifest/
│ │ ├── manifest.go
│ │ ├── proxy.json
│ │ └── server.json
│ ├── provisioner/
│ │ └── provisioner.go
│ ├── rcon/
│ │ └── rcon.go
│ └── ui/
│ ├── form.go
│ ├── spinner.go
│ ├── spinner_test.go
│ ├── table.go
│ ├── table_test.go
│ ├── ui.go
│ └── ui_test.go
├── main.go
└── minectl-skill/
├── SKILL.md
├── evals/
│ └── evals.json
└── references/
├── cli-commands.md
├── cloud-providers.md
└── manifest-schema.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .dockerignore
================================================
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
**/ssh
**/plugins
**/docs
**/config
**/*.md
DCO
.pre-commit-config.yaml
.goreleaser.yml
.gitignore
LICENSE
Makefile
renovate.json
minectl
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Go template
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
================================================
FILE: .github/CODEOWNERS
================================================
* @dirien
================================================
FILE: .github/ISSUE_TEMPLATE/bug.yaml
================================================
name: Bug Report
description: File a bug report
labels: [ bug, triage ]
assignees:
- dirien
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report! Please fill the form below.
- type: textarea
id: what-happened
attributes:
label: What happened?
description: Also tell us, what did you expect to happen?
validations:
required: true
- type: textarea
id: reproducible
attributes:
label: How can we reproduce this?
description: Please share as much information as possible. Logs, screenshots, etc.
validations:
required: true
- type: textarea
id: minectl-version
attributes:
label: minectl version
description: '`minectl version` output'
render: bash
validations:
required: true
- type: checkboxes
id: search
attributes:
label: Search
options:
- label: I did search for other open and closed issues before opening this.
required: true
- type: checkboxes
id: terms
attributes:
label: Code of Conduct
description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/dirien/.github/blob/main/CODE_OF_CONDUCT.md)
options:
- label: I agree to follow this project's Code of Conduct
required: true
- type: textarea
id: ctx
attributes:
label: Additional context
description: Anything else you would like to add
validations:
required: false
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
================================================
FILE: .github/ISSUE_TEMPLATE/feature.yaml
================================================
name: Feature Request
description: Request a new feature and/or enhancement to an existing feature
labels: [enhancement, triage]
assignees:
- dirien
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this feature request! Please fill the form below.
- type: textarea
id: is-it-a-problem
attributes:
label: Is your feature request related to a problem? Please describe.
description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
validations:
required: true
- type: textarea
id: solution
attributes:
label: Describe the solution you'd like
description: A clear and concise description of what you want to happen.
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Describe alternatives you've considered
description: A clear and concise description of any alternative solutions or features you've considered.
validations:
required: true
- type: checkboxes
id: search
attributes:
label: Search
options:
- label: I did search for other open and closed issues before opening this.
required: true
- type: checkboxes
id: terms
attributes:
label: Code of Conduct
description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/dirien/.github/blob/main/CODE_OF_CONDUCT.md)
options:
- label: I agree to follow this project's Code of Conduct
required: true
- type: textarea
id: ctx
attributes:
label: Additional context
description: Anything else you would like to add
validations:
required: false
================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
### Thank you for making `minectl 🗺` better
Please reference the issue this PR is fixing.
*Also verify you have:*
* [ ] Read the [contributions](../CONTRIBUTING.md) page.
* [ ] Read the [DCO](../DCO), if you are a first time contributor.
* [ ] Read the [code of conduct](https://github.com/dirien/.github/blob/main/CODE_OF_CONDUCT.md).
================================================
FILE: .github/dependabot.yaml
================================================
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
labels:
- "dependencies"
commit-message:
prefix: "chore(deps)"
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "weekly"
labels:
- "dependencies"
commit-message:
prefix: "chore(deps)"
================================================
FILE: .github/workflows/ci.yaml
================================================
name: build-binary
on:
push:
branches:
- '*'
tags:
- '*'
pull_request:
permissions: read-all
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
- uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Set up Go
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with:
go-version: 1.24.x
cache: false
- name: Tests
run: |
make test coverage
release:
permissions:
contents: write
id-token: write
packages: write
needs: build
env:
DOCKER_CLI_EXPERIMENTAL: "enabled"
GITHUB_TOKEN: ${{ github.token }}
HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.GH_PAT }}
runs-on: ubuntu-latest
if: success() && startsWith(github.ref, 'refs/tags/')
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
- name: Docker Login
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ github.token }}
- name: Set up Go
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with:
go-version: 1.24.x
cache: false
- uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0
- uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@ec59f474b9834571250b370d4735c50f8e2d1e29 # v7.0.0
with:
version: latest
args: release --clean
================================================
FILE: .github/workflows/lock.yml
================================================
name: lock-inactive
on:
schedule:
- cron: '0 * * * *'
permissions:
contents: read
jobs:
lock:
permissions:
issues: write
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@7266a7ce5c1df01b1c6db85bf8cd86c737dadbe7 # v6.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
issue-inactive-days: 30
pr-inactive-days: 30
issue-comment: >
This issue has been automatically locked since there
has not been any recent activity after it was closed.
Please open a new issue for related bugs.
pr-comment: >
This pull request has been automatically locked since there
has not been any recent activity after it was closed.
Please open a new issue for related bugs.
================================================
FILE: .github/workflows/ossf-scorecard-action.yaml
================================================
name: scorecards-supply-chain-security
on:
# Only the default branch is supported.
branch_protection_rule:
schedule:
# Weekly on Saturdays.
- cron: '30 1 * * 6'
push:
branches: [ main, master ]
# Declare default permissions as read only.
permissions: read-all
jobs:
analysis:
name: Scorecards analysis
runs-on: ubuntu-latest
permissions:
# Needed to upload the results to code-scanning dashboard.
id-token: write
security-events: write
actions: read
contents: read
steps:
- name: "Checkout code"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
with:
results_file: results.sarif
results_format: sarif
# Read-only PAT token. To create it,
# follow the steps in https://github.com/ossf/scorecard-action#pat-token-creation.
repo_token: ${{ secrets.SCORECARD_READ_TOKEN }}
# Publish the results for public repositories to enable scorecard badges. For more details, see
# https://github.com/ossf/scorecard-action#publishing-results.
# For private repositories, `publish_results` will automatically be set to `false`, regardless
# of the value entered here.
publish_results: true
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: SARIF file
path: results.sarif
retention-days: 5
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1
with:
sarif_file: results.sarif
================================================
FILE: .gitignore
================================================
.idea
**/passwords
**/server.properties
tmp*/
bin/
dist/
coverage.out
revive.log
**/.DS_Store
**/key.json
/minectl
**/azure.auth
**/ssh/
**/oracleidentitycloudservice_*.pem
**/*-openrc.sh
.claude/
.mcp.json
================================================
FILE: .golangci.yaml
================================================
version: "2"
formatters:
enable:
- gofumpt
- goimports
linters:
enable:
# bugs
- bodyclose
- durationcheck
- errcheck
- errorlint
- gosec
- govet
- loggercheck
- nilerr
- noctx
- recvcheck
- sqlclosecheck
# performance
- copyloopvar
- intrange
- mirror
- perfsprint
- prealloc
- usestdlibvars
# style & conventions
- asciicheck
- bidichk
- dupword
- errname
- forbidigo
- goconst
- gocritic
- gocyclo
- goprintffuncname
- misspell
- modernize
- nolintlint
- nosprintfhostport
- predeclared
- revive
- tagliatelle
- unconvert
- unparam
- wastedassign
- whitespace
# testing
- thelper
- tparallel
- usetesting
# unused / dead code
- fatcontext
- reassign
settings:
forbidigo:
forbid:
- pattern: 'ioutil\.*'
msg: "use os and io packages instead of ioutil"
exclude-godoc-examples: true
analyze-types: true
tagliatelle:
case:
use-field-name: false
rules:
yaml: goCamel
json: snake
errorlint:
asserts: true
comparison: true
errorf: true
gocritic:
enabled-tags:
- diagnostic
- style
- performance
disabled-checks:
- hugeParam
- importShadow
revive:
rules:
- name: blank-imports
- name: context-as-argument
- name: dot-imports
- name: error-naming
- name: error-return
- name: error-strings
- name: exported
disabled: true
- name: increment-decrement
- name: indent-error-flow
- name: package-comments
disabled: true
- name: range
- name: receiver-naming
- name: redefines-builtin-id
- name: superfluous-else
- name: unreachable-code
- name: var-naming
misspell:
locale: US
ignore-rules:
- organisation
gocyclo:
min-complexity: 15
perfsprint:
err-error: true
errorf: true
sprintf1: true
gosec:
excludes:
- G104
- G204
- G304
================================================
FILE: .goreleaser.yaml
================================================
version: 2
project_name: minectl
snapshot:
version_template: '{{ .Version }}-SNAPSHOT'
before:
hooks:
- go mod tidy
builds:
- env:
- CGO_ENABLED=0
goos:
- linux
- windows
- darwin
ignore:
- goos: windows
goarch: arm64
goarch:
- amd64
- arm64
mod_timestamp: '{{ .CommitTimestamp }}'
flags:
- -trimpath
source:
enabled: true
sboms:
- artifacts: archive
- id: source
artifacts: source
checksum:
name_template: 'checksums.txt'
signs:
- cmd: cosign
signature: '${artifact}.sigstore.json'
args:
- sign-blob
- '--bundle=${signature}'
- '${artifact}'
- '-y'
artifacts: all
output: true
dockers:
- image_templates: [ "ghcr.io/dirien/{{ .ProjectName }}:{{ .Version }}-amd64" ]
dockerfile: Dockerfile
use: buildx
build_flag_templates:
- --platform=linux/amd64
- --label=org.opencontainers.image.licenses=Apache-2.0
- --label=org.opencontainers.image.description=minectl is a cli for creating Minecraft server on different cloud provider
- --label=org.opencontainers.image.created={{.Date}}
- --label=org.opencontainers.image.name={{.ProjectName}}
- --label=org.opencontainers.image.revision={{.FullCommit}}
- --label=org.opencontainers.image.version={{.Version}}
- --label=org.opencontainers.image.source={{.GitURL}}
- --label=io.artifacthub.package.maintainers=[{"name":"Engin Diri","email":"engin.diri@ediri.de"}]
- --label=io.artifacthub.package.readme-url=https://raw.githubusercontent.com/dirien/minectl/main/README.md
- --label=io.artifacthub.package.logo-url=https://dirien.github.io/minectl/img/minectl-logo.png
- --label=io.artifacthub.package.keywords=minecraft,server,cli
- --label=io.artifacthub.package.license=Apache-2.0
- image_templates: [ "ghcr.io/dirien/{{ .ProjectName }}:{{ .Version }}-arm64" ]
goarch: arm64
dockerfile: Dockerfile
use: buildx
build_flag_templates:
- --platform=linux/arm64/v8
- --label=org.opencontainers.image.licenses=Apache-2.0
- --label=org.opencontainers.image.description=minectl is a cli for creating Minecraft server on different cloud provider
- --label=org.opencontainers.image.created={{.Date}}
- --label=org.opencontainers.image.name={{.ProjectName}}
- --label=org.opencontainers.image.revision={{.FullCommit}}
- --label=org.opencontainers.image.version={{.Version}}
- --label=org.opencontainers.image.source={{.GitURL}}
- --label=io.artifacthub.package.maintainers=[{"name":"Engin Diri","email":"engin.diri@ediri.de"}]
- --label=io.artifacthub.package.readme-url=https://raw.githubusercontent.com/dirien/minectl/main/README.md
- --label=io.artifacthub.package.logo-url=https://dirien.github.io/minectl/img/minectl-logo.png
- --label=io.artifacthub.package.keywords=minecraft,server,cli
- --label=io.artifacthub.package.license=Apache-2.0
docker_manifests:
- name_template: 'ghcr.io/dirien/{{ .ProjectName }}:{{ .Version }}'
image_templates:
- 'ghcr.io/dirien/{{ .ProjectName }}:{{ .Version }}-amd64'
- 'ghcr.io/dirien/{{ .ProjectName }}:{{ .Version }}-arm64'
- name_template: 'ghcr.io/dirien/{{ .ProjectName }}:latest'
image_templates:
- 'ghcr.io/dirien/{{ .ProjectName }}:{{ .Version }}-amd64'
- 'ghcr.io/dirien/{{ .ProjectName }}:{{ .Version }}-arm64'
docker_signs:
- cmd: cosign
artifacts: manifests
output: true
args:
- 'sign'
- '${artifact}'
- '-y'
brews:
- repository:
owner: dirien
name: homebrew-dirien
token: "{{ .Env.HOMEBREW_TAP_GITHUB_TOKEN }}"
commit_author:
name: dirien
email: info@ediri.de
directory: Formula
homepage: "https://github.com/dirien/minectl"
description: "minectl️️ 🗺️ is a cli for creating Minecraft (java or bedrock) server on different cloud provider."
license: "Apache License 2.0"
archives:
- format_overrides:
- goos: windows
formats: ["zip"]
nfpms:
- file_name_template: >-
{{- .ProjectName }}_
{{- title .Os }}_
{{- if eq .Arch "amd64" }}x86_64
{{- else if eq .Arch "386" }}i386
{{- else }}{{ .Arch }}{{ end }}
{{- if .Arm }}v{{ .Arm }}{{ end -}}
homepage: https://github.com/dirien/minectl
description: "minectl️️ 🗺️ is a cli for creating Minecraft (java or bedrock) server on different cloud provider."
maintainer: "Engin Diri info@ediri.de"
license: "Apache License 2.0"
vendor: minectl️️ Developers
formats:
- rpm
- deb
- apk
bindir: /usr/bin
changelog:
sort: asc
use: github
filters:
exclude:
- '^test:'
- '^chore'
- Merge pull request
- Merge remote-tracking branch
- Merge branch
- go mod tidy
groups:
- title: 'New Features'
regexp: "^.*feat[(\\w)]*:+.*$"
order: 0
- title: 'Bug fixes'
regexp: "^.*fix[(\\w)]*:+.*$"
order: 10
- title: Other work
order: 999
================================================
FILE: .pre-commit-config.yaml
================================================
repos:
- repo: https://github.com/dirien/pre-commit-hooks
rev: v0.1.0
hooks:
- id: golangci-lint
================================================
FILE: AGENTS.md
================================================
# AGENTS.md
**Precedence:** the **closest `AGENTS.md`** to the files you're changing wins. Root holds global defaults only.
## Commands (verified 2026-03-21)
> Source: Makefile, go.mod
| Task | Command | ~Time |
|------|---------|-------|
| Typecheck | `go build -v ./...` | ~15s |
| Lint | `golangci-lint run --timeout 10m -E goimports --fix` | ~30s |
| Format | `gofmt -w .` | ~5s |
| Test (single) | `go test -v -race ./internal/ui/...` | ~2s |
| Test (all) | `go test -v ./...` | ~10s |
| Build (local) | `go build .` | ~10s |
| Build (cross) | `make build` | ~30s |
| Install | `go install .` | ~10s |
| Coverage | `make coverage` | ~15s |
> If commands fail, verify against `Makefile` or ask user to update.
## Workflow
1. **Before coding**: Read nearest `AGENTS.md` for the area you're touching
2. **After each change**: Run the smallest relevant check (lint → typecheck → single test)
3. **Before committing**: Run full test suite if changes affect >2 files or touch shared code
4. **Before claiming done**: Run verification and **show output as evidence**
## File Map
```
main.go → entrypoint, injects version/commit/date
cmd/minectl/ → CLI commands (cobra): create, delete, list, update, wizard, plugins, rcon
internal/
logging/ → zap-based structured logging
manifest/ → YAML manifest parsing and JSON schema validation
provisioner/ → cloud provider orchestration via minectl-sdk
rcon/ → Minecraft RCON interactive prompt
ui/ → TUI components (spinner, table, forms via bubbletea/huh)
config/ → server config templates per Minecraft edition
docs/ → documentation and images
Dockerfile → chainguard static image, copies binary
Makefile → build, test, lint, coverage targets
```
## Golden Samples (follow these patterns)
| For | Reference | Key patterns |
|-----|-----------|--------------|
| CLI command | `cmd/minectl/create.go` | Cobra RunE, flag parsing, provisioner creation |
| Provisioner | `internal/provisioner/provisioner.go` | Interface, cloud provider switch, spinner lifecycle |
| UI component | `internal/ui/spinner.go` | Bubbletea model, headless vs interactive |
| Test pattern | `internal/ui/ui_test.go` | Table-driven tests, headless/interactive variants |
## Utilities (check before creating new)
| Need | Use | Location |
|------|-----|----------|
| Cloud provisioning | `minectl-sdk` | `github.com/dirien/minectl-sdk` (external) |
| CLI framework | `cobra` | `github.com/spf13/cobra` |
| TUI forms | `huh` | `github.com/charmbracelet/huh` |
| TUI spinners/tables | `bubbletea` + `bubbles` | `internal/ui/` |
| Logging | `zap` | `internal/logging/` |
| YAML parsing | `sigs.k8s.io/yaml` | `internal/manifest/` |
| JSON schema validation | `gojsonschema` | `internal/manifest/` |
| Error wrapping | `pkg/errors` | Used throughout |
## Heuristics (quick decisions)
| When | Do |
|------|-----|
| Adding cloud provider | Add case in `internal/provisioner/provisioner.go:getProvisioner()`, implement in `minectl-sdk` |
| Adding CLI command | New file in `cmd/minectl/`, register in `minectl.go:init()` |
| Adding server edition | New config dir under `config/`, update manifest parsing |
| Version injection | Via ldflags in Makefile: `-X main.version=...` |
| Headless mode | Use `--headless` flag; switches UI to structured logging |
| Committing | Use Conventional Commits (`feat:`, `fix:`, `docs:`, etc.) |
| Adding dependency | Ask first — we minimize deps |
| Unsure about pattern | Check Golden Samples above |
## Repository Settings
- **Default branch:** `main`
- **Go version:** 1.24.9
- **Module:** `github.com/dirien/minectl`
- **Docker:** chainguard static base image
- **CI:** GitHub Actions (lock-inactive workflow)
## Key Decisions
- **External SDK:** Core cloud logic lives in `github.com/dirien/minectl-sdk`, not in this repo. This repo is the CLI wrapper.
- **Charmbracelet TUI:** Interactive mode uses bubbletea/huh/lipgloss; headless mode falls back to zap logging.
- **Multi-cloud:** 15 cloud providers supported via provider-specific env vars (see `provisioner.go`).
- **Manifest-driven:** Server config is YAML manifests validated against JSON schema.
## Boundaries
### Always Do
- Run pre-commit checks before committing
- Add tests for new code paths
- Use conventional commit format: `type(scope): subject`
- Follow Go 1.24 conventions and idioms
- Show test output as evidence before claiming work is complete
### Ask First
- Adding new dependencies
- Modifying CI/CD configuration
- Changing public API signatures or CLI flags
- Changes to `minectl-sdk` (external dependency)
- Repo-wide refactoring or rewrites
### Never Do
- Commit secrets, credentials, or cloud provider tokens
- Modify vendor/ or generated files
- Push directly to main branch
- Use `ioutil.*` (deprecated)
- Commit go.sum without go.mod changes
## Contributing (for AI agents)
- **Comprehension**: Understand the problem before submitting code. Read the linked issue, understand *why* the change is needed.
- **Context**: Every PR must explain trade-offs and link to the issue it addresses.
- **Continuity**: Respond to review feedback. Drive-by PRs without follow-up will be closed.
## Module Boundaries
- `cmd/minectl/` → CLI layer only; no business logic, delegates to `internal/`
- `internal/provisioner/` → orchestrates `minectl-sdk`; no direct cloud API calls
- `internal/ui/` → presentation only; no business logic
- `internal/manifest/` → parsing/validation only; no side effects
- `internal/logging/` → logging setup; used by `ui`
- `internal/rcon/` → RCON protocol; standalone
## Terminology
| Term | Means |
|------|-------|
| minectl | This CLI tool for provisioning Minecraft servers |
| minectl-sdk | External Go SDK containing cloud provider implementations |
| manifest | YAML file describing desired server configuration |
| edition | Minecraft variant: java, bedrock, fabric, forge, papermc, etc. |
| RCON | Remote Console protocol for Minecraft server administration |
| headless | Non-interactive mode for CI/automation (structured log output) |
## Index of scoped AGENTS.md
| Directory | Focus |
|-----------|-------|
| [`cmd/minectl/`](./cmd/minectl/AGENTS.md) | CLI commands, cobra patterns, flag handling |
> **Agents**: When you read or edit files in a listed directory, you **must** load its AGENTS.md first.
## When instructions conflict
The nearest `AGENTS.md` wins. Explicit user prompts override files.
- For Go-specific patterns, defer to language idioms and standard library conventions
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to minectl 🗺
Welcome, and thank you for considering contributing to minectl 🗺. We encourage you to help out by raising issues,
improving documentation, fixing bugs, or adding new features
If you're interested in contributing please start by reading this document.
## Establishing a Development Environment
Establishing a development environment typically requires:
1. Forking and cloning the repository.
1. Installing development dependencies.
## Contributing Code
To contribute bug fixes or features to minectl 🗺:
1. Communicate your intent.
1. Make your changes.
1. Test your changes.
1. Update documentation and examples.
1. Open a Pull Request (PR).
Communicating your intent lets the minectl 🗺 maintainers know that you intend to contribute, and how. This sets you up
for success - you can avoid duplicating an effort that may already be underway, adding a feature that may be rejected,
or heading down a path that you would be steered away from at review time. The best way to communicate your intent is
via a detailed GitHub issue. Take a look first to see if there's already an issue relating to the thing you'd like to
contribute. If there isn't, please raise a new one! Let us know what you'd like to work on, and why.
Be sure to practice [good git commit hygiene] as you make your changes. All but the smallest changes should be broken up
into a few commits that tell a story. Use your git commits to provide context for the folks who will review PR, and the
folks who will be spelunking the codebase in the months and years to come. Ensure each of your commits is signed-off in
compliance with the [Developer Certificate of Origin] by using `git commit -s`.
All minectl 🗺 documentation and examples are under revision control; see the
[docs] and [config] directories of this repository. Any change that introduces new behaviour or changes
existing behaviour must include updates to any relevant documentation and examples. Please keep documentation and
example changes in distinct commits.
In summary, please:
* Discuss your change in a GitHub issue before you start.
* Use your Git commit messages to communicate your intent to your reviewers.
* Sign-off on all Git commits by running `git commit -s`
* Add or update tests for all changes.
* Update all relevant documentation and examples.
* If necessary, tidy up your git commit history once your PR is approved.
Thank you for reading through our contributing guide!
[good git commit hygiene]: https://www.futurelearn.com/info/blog/telling-stories-with-your-git-history
[Developer Certificate of Origin]: https://github.com/apps/dco
[docs]: docs/
[config]: config/
================================================
FILE: DCO
================================================
Developer Certificate of Origin
Version 1.1
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
660 York Street, Suite 102,
San Francisco, CA 94110 USA
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
================================================
FILE: Dockerfile
================================================
# Dockerfile
FROM cgr.dev/chainguard/static@sha256:853bfd4495abb4b65ede8fc9332513ca2626235589c2cef59b4fce5082d0836d
COPY minectl \
/usr/bin/minectl
ENTRYPOINT ["/usr/bin/minectl"]
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: Makefile
================================================
NAME := minectl
FILES := $(shell find * -type f ! -path 'vendor/*' -name '*.go')
.DEFAULT_GOAL := help
Version := $(shell git describe --tags --dirty)
GitCommit := $(shell git rev-parse HEAD)
LDFLAGS := "-s -w -X main.version=$(Version) -X main.commit=$(GitCommit)"
.PHONY: lint
lint: golangci-lint
.PHONY: golangci-lint
golangci-lint:
@hash golangci-lint > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
export BINARY="golangci-lint"; \
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(GOPATH)/bin v1.41.1; \
fi
golangci-lint run --timeout 10m -E goimports --fix
.PHONY: test
test: ## Run the tests against the codebase
go test -v ./...
.PHONY: install
install: ## Build and install locally the binary (dev purpose)
go install .
.PHONY: build-local
build-local: ## Build the binaries using local GOOS
go build .
.PHONY: run-local
run-local: ## Run the binaries locals
go run .
.PHONY: build
build: ## Build the binaries
rm -rf bin/
mkdir -p bin/
CGO_ENABLED=0 GOOS=linux go build -ldflags $(LDFLAGS) -a -installsuffix cgo -o bin/$(NAME)
CGO_ENABLED=0 GOOS=darwin go build -ldflags $(LDFLAGS) -a -installsuffix cgo -o bin/$(NAME)-darwin
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags $(LDFLAGS) -a -installsuffix cgo -o bin/$(NAME).exe
.PHONY: clean
clean: ## Remove binary if it exists
rm -f $(NAME)
.PHONY: coverage
coverage: ## Generates coverage report
rm -rf *.out
go test -v ./... -coverpkg=./... -coverprofile=coverage.out
.PHONY: all
all: test build coverage ## Test, builds and ship package for all supported platforms
.PHONY: help
help: ## Displays this help
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
================================================
FILE: README.md
================================================
## New - 1.21.11 support
`minectl 🗺`️️ supports the `Minecraft 1.21.11` version
# `minectl 🗺`




















[](https://pkg.go.dev/github.com/dirien/minectl)
[](https://goreportcard.com/report/github.com/dirien/minectl)


[](https://sonarcloud.io/summary/new_code?id=dirien_minectl)
[](https://api.securityscorecards.dev/projects/github.com/dirien/minectl)
[](https://bestpractices.coreinfrastructure.org/projects/5238)

[](https://artifacthub.io/packages/search?repo=minectl)
`minectl 🗺`️️ is a CLI for creating Minecraft servers on different cloud providers.
It is a private side project of me, to learn more about Go, CLI and multi-cloud environments.
## Table of Contents
- [Supported Cloud Providers](#supported-cloud-providers)
- [Quick Start](#quick-start)
- [Documentation](#documentation)
- [Getting Started Guides](#getting-started-guides)
- [Known Limitations](#known-limitations)
- [Contributing](#contributing)
- [Roadmap](#roadmap)
- [Libraries & Tools](#libraries--tools)
- [Legal Disclaimer](#legal-disclaimer)
## Supported Cloud Providers
| Provider | Website |
|----------|---------|
| Civo | https://www.civo.com/ |
| Scaleway | https://www.scaleway.com |
| DigitalOcean | https://www.digitalocean.com/ |
| Hetzner | https://www.hetzner.com/ |
| Akamai Connected Cloud | https://www.linode.com/ |
| OVHCloud | https://www.ovh.com/ |
| Google Compute Engine (GCE) | https://cloud.google.com/compute |
| Vultr | https://www.vultr.com/ |
| Azure | https://azure.microsoft.com/en-us/ |
| Oracle Cloud Infrastructure | https://www.oracle.com/cloud/ |
| Amazon AWS | https://aws.amazon.com/ |
| VEXXHOST | https://vexxhost.com/ |
| Multipass | https://multipass.run/ |
| Exoscale | https://www.exoscale.com/ |
| Fuga Cloud | https://fuga.cloud/ |
## Quick Start
### Installation
#### Linux/macOS (Installation Script)
```bash
curl -sLS https://get.minectl.dev | sudo sh
```
or without `sudo`:
```bash
curl -sLS https://get.minectl.dev | sh
```
#### macOS (Homebrew)
```bash
brew tap dirien/homebrew-dirien
brew install minectl
```
#### Windows (PowerShell)
```powershell
# Create directory
New-Item -Path "$HOME/minectl/cli" -Type Directory
# Download file
Start-BitsTransfer -Source https://github.com/dirien/minectl/releases/download/v0.7.0/minectl_0.7.0_windows_amd64.zip -Destination "$HOME/minectl/cli/."
# Uncompress zip file
Expand-Archive $HOME/minectl/cli/*.zip -DestinationPath $HOME/minectl/cli/.
# Add to Windows Environment Variables
[Environment]::SetEnvironmentVariable("Path",$($env:Path + ";$Home\minectl\cli"),'User')
```
#### From Source
```bash
git clone https://github.com/dirien/minectl
cd minectl
make build
```
### Create Your First Server
1. **Set up authentication** for your cloud provider ([see docs](docs/authentication.md))
2. **Create a config file** using the wizard:
```bash
minectl wizard
```
3. **Create the server**:
```bash
minectl create --filename server.yaml
```
4. **Connect and play!**
[](https://asciinema.org/a/439572)
## Documentation
| Document | Description |
|----------|-------------|
| [Architecture](docs/architecture.md) | High-level architectural overview |
| [Authentication](docs/authentication.md) | Cloud provider credentials setup |
| [Configuration](docs/configuration.md) | Server and proxy configuration reference |
| [CLI Reference](docs/cli-reference.md) | All commands and flags |
| [Editions](docs/editions.md) | Supported Minecraft server and proxy editions |
| [Features](docs/features.md) | Monitoring, volumes, security, and more |
## Getting Started Guides
- [Civo Java Edition](docs/getting-started-civo.md)
- [Civo Bedrock Edition](docs/getting-started-civo-bedrock.md)
- [Scaleway Java Edition](docs/getting-started-scaleway.md)
- [GCE Edition](docs/getting-started-gce.md)
- [Exoscale Edition](docs/getting-started-exoscale.md)
- [Multi-cloud server monitoring](docs/multi-server-monitoring-civo.md)
- [LuckyBlocks on Scaleway](docs/running-minecraft-luckyblocks-budget-scaleway.md)
- [PaperMC SkyBlock on Hetzner](docs/skyblock-papermc-hetzner.md)
## Known Limitations
`minectl 🗺` is still under development. There will be the possibility for breaking changes.
## Contributing
Feel free to join! See our [contribution guidelines](CONTRIBUTING.md).
**License:** Apache License, Version 2.0
## Roadmap
- [x] Support Bedrock edition [#10](https://github.com/dirien/minectl/issues/10)
- [x] Add monitoring capabilities [#21](https://github.com/dirien/minectl/issues/21)
- [x] List Minecraft Server [#11](https://github.com/dirien/minectl/issues/11)
- [x] Update Minecraft Server [#12](https://github.com/dirien/minectl/issues/12)
- [x] Hetzner support [#26](https://github.com/dirien/minectl/issues/26)
- [x] Linode support [#31](https://github.com/dirien/minectl/issues/31)
- [x] OVHCloud support [#43](https://github.com/dirien/minectl/issues/43)
- [x] GCE support [#55](https://github.com/dirien/minectl/issues/55)
- [x] Modded editions [#20](https://github.com/dirien/minectl/issues/20)
- [x] Vultr support [#90](https://github.com/dirien/minectl/issues/90)
- [x] Proxy servers (BungeeCord/Waterfall) [#95](https://github.com/dirien/minectl/issues/95)
- [x] Azure support [#56](https://github.com/dirien/minectl/issues/56)
- [x] Oracle/OCI support [#107](https://github.com/dirien/minectl/issues/107)
- [x] AWS support [#210](https://github.com/dirien/minectl/pull/210)
- [ ] Much more to come...
## Libraries & Tools
Click to expand
- https://github.com/charmbracelet/bubbletea
- https://github.com/charmbracelet/lipgloss
- https://github.com/charmbracelet/huh
- https://github.com/charmbracelet/bubbles
- https://github.com/melbahja/goph
- https://github.com/spf13/cobra
- https://github.com/goreleaser
- https://github.com/civo/civogo
- https://github.com/digitalocean/godo
- https://github.com/scaleway/scaleway-sdk-go
- https://github.com/linode/linodego
- https://github.com/hetznercloud/hcloud-go
- https://github.com/sethvargo/go-password
- https://github.com/ovh/go-ovh
- https://github.com/dirien/ovh-go-sdk
- https://github.com/hashicorp/go-retryablehttp
- https://github.com/googleapis/google-api-go-client
- https://github.com/Masterminds/sprig
- https://github.com/Tnze/go-mc
- https://github.com/c-bata/go-prompt
- https://github.com/vultr/govultr
- https://github.com/Azure/azure-sdk-for-go
- https://github.com/blang/semver
- https://github.com/tcnksm/go-latest
- https://github.com/uber-go/zap
- https://github.com/oracle/oci-go-sdk
- https://github.com/aws/aws-sdk-go-v2
- https://github.com/gophercloud/gophercloud
- https://github.com/exoscale/egoscale
## Legal Disclaimer
This project is not affiliated with Mojang Studios, XBox Game Studios, Double Eleven or the Minecraft brand.
"Minecraft" is a trademark of Mojang Synergies AB.
Other trademarks referenced herein are property of their respective owners.
## Stargazers over time
[](https://starchart.cc/dirien/minectl)
================================================
FILE: SECURITY.md
================================================
# Security Policies and Procedures
This document outlines security procedures and general policies for the `minectl 🗺`
project.
* [Reporting a Bug](#reporting-a-bug)
* [Disclosure Policy](#disclosure-policy)
* [Comments on this Policy](#comments-on-this-policy)
## Reporting a Bug
The `minectl 🗺` team and community take all security bugs in `minectl 🗺`
seriously. Thank you for improving the security of `minectl 🗺`. We appreciate your efforts and
responsible disclosure and will make every effort to acknowledge your contributions.
Report security bugs by emailing the lead maintainer at engin.diri@ediri.de.
The lead maintainer will acknowledge your email within 48 hours, and will send a more detailed response within 48 hours
indicating the next steps in handling your report. After the initial reply to your report, the security team will
endeavor to keep you informed of the progress towards a fix and full announcement, and may ask for additional
information or guidance.
Report security bugs in third-party modules to the person or team maintaining the module.
## Disclosure Policy
When the security team receives a security bug report, they will assign it to a primary handler. This person will
coordinate the fix and release process, involving the following steps:
* Confirm the problem and determine the affected versions.
* Audit code to find any potential similar problems.
* Prepare fixes for all releases still under maintenance. These fixes will be released as fast as possible to npm.
## Comments on this Policy
If you have suggestions on how this process could be improved please submit a pull request.
================================================
FILE: artifacthub-repo.yml
================================================
# ID is for the OCI Image
repositoryID: 71cfb056-f17b-4d72-8e10-a3437303a257
owners:
- name: Engin Diri
email: engin.diri@ediri.de
================================================
FILE: cmd/minectl/AGENTS.md
================================================
# AGENTS.md — cmd/minectl (CLI Commands)
## Overview
Cobra-based CLI entry point for minectl. Each file defines one subcommand. All commands delegate to `internal/` packages for business logic.
## Key Files
| File | Purpose |
|------|---------|
| `minectl.go` | Root command, global flags (`--headless`, `--verbose`, `--log-encoding`), version check, subcommand registration in `init()` |
| `create.go` | `minectl create` — provisions a Minecraft server from manifest |
| `delete.go` | `minectl delete` — tears down a server by ID |
| `update.go` | `minectl update` — updates server edition/config |
| `list.go` | `minectl list` — lists servers for a given provider/region |
| `rcon.go` | `minectl rcon` — opens interactive RCON console |
| `plugins.go` | `minectl plugins` — uploads plugins to a running server |
| `wizard.go` | `minectl wizard` — interactive TUI wizard for server creation |
## Golden Samples (follow these patterns)
| For | Reference | Key patterns |
|-----|-----------|--------------|
| Standard CRUD command | `create.go` | `RunE` + `RunFunc` wrapper, flag setup, provisioner factory |
| Root + global flags | `minectl.go` | `PersistentPreRunE` for logging/UI setup, `PersistentPostRunE` for version check |
| Interactive command | `wizard.go` | Uses `internal/ui/form.go` for TUI prompts |
## Setup & environment
- **CLI framework:** Cobra (`github.com/spf13/cobra`)
- **Build output:** `bin/minectl` (linux), `bin/minectl-darwin`, `bin/minectl.exe` (windows)
- Version injected via ldflags: `main.version`, `main.commit`, `main.date`
## Build & tests
- Build: `go build .` or `make build` (cross-platform)
- Run: `go run .`
- Test: `go test -v ./...` (tests are in `internal/`, not here)
- Lint: `golangci-lint run --timeout 10m -E goimports --fix`
## Code style & conventions
- Use Cobra `RunE` (not `Run`) for commands that can fail
- Wrap `RunE` with `RunFunc()` from `minectl.go` for consistent error handling + exit codes
- Common flag sets: `--filename` (manifest), `--id` (server ID), `--ssh-key` (private key path)
- `createUpdatePluginProvisioner()` is the shared factory for commands needing a provisioner
- Register new commands in `init()` inside `minectl.go`
- Provide `--help` text for all commands and flags
- Exit codes: 0 = success, 1 = error (via `os.Exit` in `RunFunc`)
- Errors: displayed via `minectlUI.ErrorMsg()` (stderr in headless, TUI in interactive)
- `--headless` flag: enables structured logging, disables TUI rendering
## Security & safety
- Cloud credentials come from environment variables only — never from flags or config files
- Never log or display cloud tokens
- Validate manifest paths before reading
- SSH key paths: validate existence, do not log contents
## PR/commit checklist
- [ ] `--help` text is clear and accurate for new/modified commands
- [ ] New command registered in `minectl.go:init()`
- [ ] Uses `RunFunc` wrapper for error handling
- [ ] Flags have meaningful defaults and descriptions
- [ ] Works in both interactive and `--headless` mode
- [ ] Errors go through `minectlUI.ErrorMsg()`
## Patterns to Follow
> **Prefer looking at real code in this repo over generic examples.**
> See **Golden Samples** section above for files that demonstrate correct patterns.
## When stuck
- Cobra docs: see `github.com/spf13/cobra` README
- Check existing commands (especially `create.go`) for patterns
- Root AGENTS.md for project-wide conventions
================================================
FILE: cmd/minectl/create.go
================================================
package minectl
import (
"fmt"
"github.com/dirien/minectl/internal/provisioner"
"github.com/dirien/minectl/internal/ui"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
func init() {
createCmd.Flags().StringP("filename", "f", "", "Location of the manifest file")
_ = createCmd.Flags().SetAnnotation("filename", cobra.BashCompFilenameExt, []string{"yaml"})
createCmd.Flags().BoolP("wait", "w", true, "Wait for Minecraft Server is started")
}
var createCmd = &cobra.Command{
Use: "create",
Short: "Create an Minecraft Server.",
Example: `minectl create \
--filename server-do.yaml`,
RunE: RunFunc(runCreate),
SilenceUsage: true,
SilenceErrors: true,
}
func runCreate(cmd *cobra.Command, _ []string) error {
filename, err := cmd.Flags().GetString("filename")
if filename == "" {
return errors.New("Please provide a valid manifest file via -f|--filename flag")
}
if err != nil {
return errors.Wrap(err, "Please provide a valid manifest file")
}
p, err := provisioner.NewProvisioner(&provisioner.MinectlProvisionerOpts{
ManifestPath: filename,
}, minectlUI)
if err != nil {
return err
}
wait := true
if cmd.Flags().Changed("wait") {
wait, _ = cmd.Flags().GetBool("wait")
}
res, err := p.CreateServer(wait)
if err != nil {
return err
}
if !headless {
table := ui.NewTable(minectlUI, "ID", "NAME", "REGION", "TAGS", "IP")
table.Append([]string{res.ID, res.Name, res.Region, res.Tags, res.PublicIP})
fmt.Println("")
table.Render()
minectlUI.Info(fmt.Sprintf("To delete the server:\n\n minectl delete -f %s --id %s", filename, res.ID))
minectlUI.Info(fmt.Sprintf("To update the server:\n\n minectl update -f %s --id %s", filename, res.ID))
minectlUI.Info(fmt.Sprintf("To connect via RCON:\n\n minectl rcon -f %s --id %s", filename, res.ID))
minectlUI.Warn("Beta features:")
minectlUI.Info(fmt.Sprintf("To upload a plugin:\n\n minectl plugins -f %s --id %s --plugin /x.jar --destination /minecraft/plugins", filename, res.ID))
}
return nil
}
================================================
FILE: cmd/minectl/delete.go
================================================
package minectl
import (
"github.com/dirien/minectl/internal/provisioner"
"github.com/dirien/minectl/internal/ui"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
func init() {
deleteCmd.Flags().StringP("filename", "f", "", "Location of the manifest file")
_ = deleteCmd.Flags().SetAnnotation("filename", cobra.BashCompFilenameExt, []string{"yaml"})
deleteCmd.Flags().String("id", "", "Contains the server id")
deleteCmd.Flags().BoolP("yes", "y", false, "Automatically delete the server")
}
var deleteCmd = &cobra.Command{
Use: "delete",
Short: "Delete an Minecraft Server.",
Example: `mincetl delete \
--filename server-do.yaml
--id xxx-xxx-xxx-xxx
`,
RunE: RunFunc(runDelete),
SilenceUsage: true,
SilenceErrors: true,
}
func runDelete(cmd *cobra.Command, _ []string) error {
filename, err := cmd.Flags().GetString("filename")
if err != nil {
return errors.Wrap(err, "failed to get 'filename' value")
}
if filename == "" {
return errors.New("Please provide a valid manifest file via -f|--filename flag")
}
id, err := cmd.Flags().GetString("id")
if err != nil {
return err
}
if id == "" {
return errors.New("Please provide a valid id")
}
newProvisioner, err := provisioner.NewProvisioner(&provisioner.MinectlProvisionerOpts{
ManifestPath: filename,
ID: id,
}, minectlUI)
if err != nil {
return err
}
yes := cmd.Flag("yes").Changed
if yes {
err = newProvisioner.DeleteServer()
if err != nil {
return err
}
} else {
confirmed, err := ui.Confirm("Do you want to delete the Minecraft server?")
if err != nil {
return err
}
if confirmed {
err = newProvisioner.DeleteServer()
if err != nil {
return err
}
} else {
minectlUI.Warn("Delete canceled.")
}
}
return nil
}
================================================
FILE: cmd/minectl/list.go
================================================
package minectl
import (
"fmt"
"github.com/dirien/minectl/internal/provisioner"
"github.com/dirien/minectl/internal/ui"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
func init() {
listCmd.Flags().StringP("provider", "p", "", "The cloud provider - civo|scaleway|do|hetzner|akamai|ovh|gce|vultr|azure|oci|aws|vexxhost|fuga|multipass|exoscale")
listCmd.Flags().StringP("region", "r", "", "The region (gce: zone) for your cloud provider - civo|gce")
}
var listCmd = &cobra.Command{
Use: "list",
Short: "List all Minecraft Server.",
Example: `mincetl list \
--provider civo \
--region LON1`,
RunE: RunFunc(runList),
SilenceUsage: true,
SilenceErrors: true,
}
func runList(cmd *cobra.Command, _ []string) error {
provider, err := cmd.Flags().GetString("provider")
if err != nil {
return errors.Wrap(err, "failed to get 'provider' value")
}
if provider == "" {
return errors.New("Please provide a valid 'provider' value")
}
region, err := cmd.Flags().GetString("region")
if err != nil {
return errors.Wrap(err, "failed to get 'region' value")
}
newProvisioner, err := provisioner.ListProvisioner(&provisioner.MinectlProvisionerListOpts{
Provider: provider,
Region: region,
}, minectlUI)
if err != nil {
return err
}
servers, err := newProvisioner.ListServer()
if err != nil {
return err
}
if len(servers) == 0 {
minectlUI.Info("No servers found")
return nil
}
if !headless {
fmt.Println("")
table := ui.NewTable(minectlUI, "ID", "NAME", "REGION", "TAGS", "IP")
for _, server := range servers {
table.Append([]string{server.ID, server.Name, server.Region, server.Tags, server.PublicIP})
}
table.Render()
}
return nil
}
================================================
FILE: cmd/minectl/minectl.go
================================================
package minectl
import (
"bytes"
"context"
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
"strings"
"go.uber.org/zap"
"github.com/blang/semver/v4"
"github.com/dirien/minectl/internal/logging"
"github.com/dirien/minectl/internal/provisioner"
"github.com/dirien/minectl/internal/ui"
"github.com/mitchellh/go-homedir"
"github.com/morikuni/aec"
pkgerrors "github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/tcnksm/go-latest"
)
var (
Version string
GitCommit string
Date string
)
func createUpdatePluginProvisioner(cmd *cobra.Command) (provisioner.Provisioner, error) {
filename, err := cmd.Flags().GetString("filename")
if err != nil {
return nil, pkgerrors.Wrap(err, "Please provide a valid manifest file")
}
if filename == "" {
return nil, pkgerrors.New("Please provide a valid manifest file via -f|--filename flag")
}
id, err := cmd.Flags().GetString("id")
if err != nil {
return nil, err
}
if id == "" {
return nil, pkgerrors.New("Please provide a valid id")
}
sshKey, err := cmd.Flags().GetString("ssh-key")
if err != nil {
return nil, err
}
if sshKey == "" {
return nil, pkgerrors.New("Please provide a valid ssh key path")
}
p, err := provisioner.NewProvisioner(&provisioner.MinectlProvisionerOpts{
ManifestPath: filename,
ID: id,
SSHPrivateKeyPath: sshKey,
}, minectlUI)
if err != nil {
return nil, err
}
return p, nil
}
func isDevVersion(s semver.Version) bool {
if len(s.Pre) == 0 {
return false
}
devStrings := regexp.MustCompile(`alpha|beta|dev|rc`)
return !s.Pre[0].IsNum && devStrings.MatchString(s.Pre[0].VersionStr)
}
func isBrewInstall(exe string) (bool, error) {
if runtime.GOOS != "darwin" {
return false, nil
}
exePath, err := filepath.EvalSymlinks(exe)
if err != nil {
return false, err
}
brewBin, err := exec.LookPath("brew")
if err != nil {
return false, err
}
brewPrefixCmd := exec.CommandContext(context.Background(), brewBin, "--prefix", "minectl")
var stdout bytes.Buffer
var stderr bytes.Buffer
brewPrefixCmd.Stdout = &stdout
brewPrefixCmd.Stderr = &stderr
if err = brewPrefixCmd.Run(); err != nil {
var ee *exec.ExitError
if errors.As(err, &ee) {
ee.Stderr = stderr.Bytes()
}
return false, pkgerrors.Wrapf(err, "'brew --prefix minectl' failed")
}
brewPrefixCmdOutput := strings.TrimSpace(stdout.String())
if brewPrefixCmdOutput == "" {
return false, pkgerrors.New("trimmed output from 'brew --prefix minectl' is empty")
}
brewPrefixPath, err := filepath.EvalSymlinks(brewPrefixCmdOutput)
if err != nil {
return false, err
}
brewPrefixExePath := filepath.Join(brewPrefixPath, "minectl")
return exePath == brewPrefixExePath, nil
}
func runPostCommandHooks(c *cobra.Command, args []string) error {
if c.PostRunE != nil {
if err := c.PostRunE(c, args); err != nil {
return err
}
} else if c.PostRun != nil {
c.PostRun(c, args)
}
for p := c; p != nil; p = p.Parent() {
if p.PersistentPostRunE != nil {
if err := p.PersistentPostRunE(c, args); err != nil {
return err
}
break
} else if p.PersistentPostRun != nil {
p.PersistentPostRun(c, args)
break
}
}
return nil
}
func RunFunc(run func(cmd *cobra.Command, args []string) error) func(*cobra.Command, []string) error {
return func(cmd *cobra.Command, args []string) error {
if res := run(cmd, args); res != nil {
minectlUI.ErrorMsg(res)
if postRunErr := runPostCommandHooks(cmd, args); postRunErr != nil {
minectlUI.ErrorMsg(postRunErr)
}
os.Exit(1)
}
os.Exit(0)
return nil
}
}
func getUpgradeCommand() string {
exe, err := os.Executable()
if err != nil {
return ""
}
isBrew, err := isBrewInstall(exe)
if err != nil {
fmt.Printf("error determining if the running executable was installed with brew: %s", err)
}
if isBrew {
return "$ brew upgrade minectl"
}
if runtime.GOOS != "windows" {
return "$ curl -sSL https://get.minectl.dev | sh"
}
return ""
}
func getUpgradeMessage(latestVer, current *semver.Version) *string {
cmd := getUpgradeCommand()
msg := fmt.Sprintf("A new version of minectl is available. To upgrade from version '%s' to '%s', ", current, latestVer)
if cmd != "" {
msg += "run \n " + cmd + "\n\nor "
}
msg += "visit https://github.com/dirien/minectl#installing-minectl- for manual instructions."
return &msg
}
func getCLIVersionInfo(current *semver.Version) (*semver.Version, error) {
githubTag := &latest.GithubTag{
Owner: "dirien",
Repository: "minectl",
}
res, err := latest.Check(githubTag, current.String())
if err != nil {
return nil, err
}
version, err := semver.New(res.Current)
if err != nil {
return nil, err
}
return version, nil
}
func checkForUpdate() *string {
curVer, err := semver.ParseTolerant(getVersion())
if err != nil {
fmt.Printf("error parsing current version: %s", err)
}
if isDevVersion(curVer) {
return nil
}
latestVer, err := getCLIVersionInfo(&curVer)
if err != nil {
return nil
}
if latestVer.GT(curVer) {
return getUpgradeMessage(latestVer, &curVer)
}
return nil
}
var versionCmd = &cobra.Command{
Use: "version",
Short: "Display the clients version information.",
Run: parseBaseCommand,
}
func getVersion() string {
if Version != "" {
return Version
}
return "0.1.0-dev"
}
func parseBaseCommand(_ *cobra.Command, _ []string) {
printLogo()
fmt.Println("Version:", getVersion())
fmt.Println("Git Commit:", GitCommit)
fmt.Println("Build date:", Date)
}
var (
headless bool
minectlLog *logging.MinectlLogging
minectlUI *ui.UI
updateCheckResult chan *string
)
var minectlCmd = &cobra.Command{
Use: "minectl",
Short: "Create Minecraft Server on different cloud provider.",
Run: runMineCtl,
CompletionOptions: cobra.CompletionOptions{
DisableDefaultCmd: false,
},
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
headless, _ = cmd.Flags().GetBool("headless")
verbose, _ := cmd.Flags().GetString("verbose")
logEncoding, _ := cmd.Flags().GetString("log-encoding")
if headless && verbose == "" {
verbose = "info"
}
var err error
minectlLog, err = logging.NewLogging(verbose, logEncoding, headless)
if err != nil {
os.Exit(0)
}
minectlUI = ui.NewUI(headless, minectlLog)
var waitForUpdateCheck bool
defer func() {
if !waitForUpdateCheck {
close(updateCheckResult)
}
}()
updateCheckResult = make(chan *string)
waitForUpdateCheck = true
go func() {
updateCheckResult <- checkForUpdate()
close(updateCheckResult)
}()
return nil
},
PersistentPostRunE: func(_ *cobra.Command, _ []string) error {
checkVersionMsg, ok := <-updateCheckResult
if ok && checkVersionMsg != nil {
zap.S().Infof("Warning(%v)", checkVersionMsg)
fmt.Println()
fmt.Println(*checkVersionMsg)
}
return nil
},
}
func makeAppDirectoryIfNotExists() {
dir, err := homedir.Dir()
if err != nil {
fmt.Printf("error determining the home directory: %s", err)
}
path := dir + "/.minectl"
if _, err := os.Stat(path); os.IsNotExist(err) {
err := os.Mkdir(path, os.ModeDir|0o755)
if err != nil {
fmt.Printf("error while creating the minectl directory: %s", err)
}
}
}
func GetHomeFolder() string {
dir, err := homedir.Dir()
if err != nil {
fmt.Printf("error determining the home directory: %s", err)
}
return dir + "/.minectl"
}
func init() {
makeAppDirectoryIfNotExists()
minectlCmd.PersistentFlags().String("verbose", "",
"Enable verbose logging: debug|info|warn|error|dpanic|panic|fatal")
minectlCmd.PersistentFlags().String("log-encoding", "console",
"Set the log encoding: console|json (default: console)")
minectlCmd.PersistentFlags().Bool("headless", false,
"Set this value to if mincetl is called by a CI system. Enables logging and disables human-readable output rendering (default: false)")
minectlCmd.AddCommand(versionCmd)
minectlCmd.AddCommand(createCmd)
minectlCmd.AddCommand(deleteCmd)
minectlCmd.AddCommand(listCmd)
minectlCmd.AddCommand(wizardCmd)
minectlCmd.AddCommand(pluginCmd)
minectlCmd.AddCommand(rconCmd)
minectlCmd.AddCommand(updateCmd)
}
func Execute(version, gitCommit, date string) error {
Version = version
GitCommit = gitCommit
Date = date
return minectlCmd.Execute()
}
func runMineCtl(cmd *cobra.Command, _ []string) {
printLogo()
err := cmd.Help()
if err != nil {
os.Exit(0)
}
}
func printLogo() {
minectlLogo := aec.WhiteF.Apply(minectlFigletStr)
fmt.Println(minectlLogo)
}
const minectlFigletStr = `
_______ _____ __ _ _______ _______ _______
| | | | | \ | |______ | | |
| | | __|__ | \_| |______ |_____ | |_____
`
================================================
FILE: cmd/minectl/plugins.go
================================================
package minectl
import (
"github.com/spf13/cobra"
)
func init() {
pluginCmd.Flags().StringP("filename", "f", "", "Location of the manifest file")
_ = pluginCmd.Flags().SetAnnotation("filename", cobra.BashCompFilenameExt, []string{"yaml"})
pluginCmd.Flags().String("id", "", "contains the server id")
pluginCmd.Flags().StringP("plugin", "p", "", "Location of the plugin")
_ = pluginCmd.Flags().SetAnnotation("plugin", cobra.BashCompFilenameExt, []string{"jar"})
pluginCmd.Flags().StringP("destination", "d", "", "Plugin destination folder")
_ = pluginCmd.Flags().SetAnnotation("destination", cobra.BashCompSubdirsInDir, []string{})
pluginCmd.Flags().StringP("ssh-key", "k", "", "specify a specific path for the SSH key")
}
type ModType string
const (
Forge ModType = "forge"
Fabric ModType = "fabric"
)
type Plugin struct {
Name string
Mod ModType
Version []string
DownloadURL string
Destination string
}
var pluginCmd = &cobra.Command{
Use: "plugins",
Short: "Manage your plugins for a specific server",
Example: `mincetl plugins \
--filename server-do.yaml
--id xxx-xxx-xxx-xxx
--plugin plugin.jar
--destination /minecraft/mods`,
RunE: RunFunc(runPlugin),
SilenceUsage: true,
SilenceErrors: true,
}
var _ = []Plugin{
{
Name: "Fabric API",
Mod: Fabric,
Version: []string{"0.37.1+1.16", "0.37.1+1.17"},
DownloadURL: "https://github.com/FabricMC/fabric/releases/download/{{ .Version }}/fabric-api-{{ .Version }}.jar",
Destination: "/mincraft/mods",
},
}
func runPlugin(cmd *cobra.Command, _ []string) error {
p, err := createUpdatePluginProvisioner(cmd)
if err != nil {
return err
}
plugin, _ := cmd.Flags().GetString("plugin")
destination, _ := cmd.Flags().GetString("destination")
err = p.UploadPlugin(plugin, destination)
if err != nil {
return err
}
return err
}
================================================
FILE: cmd/minectl/rcon.go
================================================
package minectl
import (
"github.com/dirien/minectl/internal/provisioner"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
func init() {
rconCmd.Flags().StringP("filename", "f", "", "Location of the manifest file")
_ = rconCmd.Flags().SetAnnotation("filename", cobra.BashCompFilenameExt, []string{"yaml"})
rconCmd.Flags().String("id", "", "contains the server id")
}
var rconCmd = &cobra.Command{
Use: "rcon",
Short: "RCON client to your Minecraft server.",
Example: `mincetl rcon \
--filename server-do.yaml \
--id xxxx`,
RunE: RunFunc(runRCON),
SilenceUsage: true,
SilenceErrors: true,
}
func runRCON(cmd *cobra.Command, _ []string) error {
filename, err := cmd.Flags().GetString("filename")
if filename == "" {
return errors.New("Please provide a valid manifest file via -f|--filename flag")
}
if err != nil {
return errors.Wrap(err, "Please provide a valid manifest file")
}
id, err := cmd.Flags().GetString("id")
if err != nil {
return err
}
if id == "" {
return errors.New("Please provide a valid id")
}
p, err := provisioner.NewProvisioner(&provisioner.MinectlProvisionerOpts{
ManifestPath: filename,
ID: id,
}, minectlUI)
if err != nil {
return err
}
err = p.DoRCON()
if err != nil {
return err
}
return nil
}
================================================
FILE: cmd/minectl/update.go
================================================
package minectl
import (
"github.com/spf13/cobra"
)
func init() {
updateCmd.Flags().StringP("filename", "f", "", "Location of the manifest file")
updateCmd.Flags().StringP("ssh-key", "k", "", "specify a specific path for the SSH key")
_ = updateCmd.Flags().SetAnnotation("filename", cobra.BashCompFilenameExt, []string{"yaml"})
updateCmd.Flags().String("id", "", "contains the server id")
}
var updateCmd = &cobra.Command{
Use: "update",
Short: "Update an Minecraft Server.",
Example: `mincetl update \
--filename server-do.yaml
--id xxx-xxx-xxx-xxx`,
RunE: RunFunc(runUpdate),
SilenceUsage: true,
SilenceErrors: true,
}
func runUpdate(cmd *cobra.Command, _ []string) error {
p, err := createUpdatePluginProvisioner(cmd)
if err != nil {
return err
}
err = p.UpdateServer()
if err != nil {
return err
}
return err
}
================================================
FILE: cmd/minectl/wizard.go
================================================
package minectl
import (
"errors"
"fmt"
"os"
"regexp"
"strconv"
"strings"
"github.com/charmbracelet/huh"
"github.com/dirien/minectl-sdk/common"
"github.com/dirien/minectl-sdk/model"
"github.com/dirien/minectl-sdk/template"
"github.com/dirien/minectl/internal/ui"
"github.com/spf13/cobra"
)
var wizardCmd = &cobra.Command{
Use: "wizard",
Short: "Calls the minectl wizard to create interactively a minectl config",
Example: `mincetl wizard`,
RunE: RunFunc(runWizard),
SilenceUsage: true,
SilenceErrors: true,
}
func init() {
wizardCmd.Flags().StringP("output", "o", "", "output folder for the configuration file for minectl (default: ~/.minectl)")
_ = wizardCmd.Flags().SetAnnotation("output", cobra.BashCompSubdirsInDir, []string{})
}
// Provider options for the wizard
var providerOptions = []huh.Option[string]{
huh.NewOption("DigitalOcean", "DigitalOcean"),
huh.NewOption("Civo", "Civo"),
huh.NewOption("Scaleway", "Scaleway"),
huh.NewOption("Hetzner", "Hetzner"),
huh.NewOption("Akamai Connected Cloud", "Akamai Connected Cloud"),
huh.NewOption("OVHcloud", "OVHcloud"),
huh.NewOption("Google Compute Engine", "Google Compute Engine"),
huh.NewOption("vultr", "vultr"),
huh.NewOption("Azure", "Azure"),
huh.NewOption("Oracle Cloud Infrastructure", "Oracle Cloud Infrastructure"),
huh.NewOption("Amazon Web Services", "Amazon Web Services"),
huh.NewOption("VEXXHOST", "VEXXHOST"),
huh.NewOption("Ubuntu Multipass", "Ubuntu Multipass"),
huh.NewOption("Exoscale", "Exoscale"),
huh.NewOption("Fuga Cloud", "Fuga Cloud"),
}
var javaVersionOptions = []huh.Option[string]{
huh.NewOption("Java 8", "8"),
huh.NewOption("Java 16", "16"),
huh.NewOption("Java 17", "17"),
}
var editionOptions = []huh.Option[string]{
huh.NewOption("Bedrock", "bedrock"),
huh.NewOption("Nukkit", "nukkit"),
huh.NewOption("PowerNukkit", "powernukkit"),
huh.NewOption("CraftBukkit", "craftbukkit"),
huh.NewOption("Fabric", "fabric"),
huh.NewOption("Forge", "forge"),
huh.NewOption("Java (Vanilla)", "java"),
huh.NewOption("PaperMC", "papermc"),
huh.NewOption("Spigot", "spigot"),
huh.NewOption("Purpur", "purpur"),
}
var featureOptions = []huh.Option[string]{
huh.NewOption("Monitoring", "Monitoring"),
huh.NewOption("RCON", "RCON"),
}
// isBedrockEdition returns true for editions that don't use Java.
func isBedrockEdition(edition string) bool {
return edition == "bedrock" || edition == "nukkit" || edition == "powernukkit"
}
func runWizard(cmd *cobra.Command, _ []string) error {
minectlUI.Info("minectl configuration file wizard")
wizard := model.Wizard{
SSHPort: "22",
BanTime: "600",
MaxRetry: "6",
Java: "16",
Heap: "2G",
Edition: "java",
}
var features []string
// Validation functions
nameValidator := func(s string) error {
if s == "" {
return errors.New("please enter the name of your Minecraft server")
}
match, _ := regexp.MatchString(common.NameRegex, s)
if !match {
return errors.New("the name must consist of lower case alphanumeric characters or '-'")
}
return nil
}
requiredValidator := func(s string) error {
if s == "" {
return errors.New("this field is required")
}
return nil
}
portValidator := func(s string) error {
if s == "" {
return errors.New("this field is required")
}
port, err := strconv.Atoi(s)
if err != nil || port < 1 || port > 65535 {
return errors.New("enter a valid port number (1-65535)")
}
return nil
}
heapValidator := func(s string) error {
if s == "" {
return errors.New("this field is required")
}
if !strings.Contains(s, "G") {
return errors.New("enter the Java heap size in following notation G, eg 2G")
}
return nil
}
// Group 1: Server basics
basicGroup := huh.NewGroup(
huh.NewInput().
Title("Server Name").
Description("Enter the name of your Minecraft server").
Value(&wizard.Name).
Validate(nameValidator),
huh.NewSelect[string]().
Title("Cloud Provider").
Description("Choose a cloud provider").
Options(providerOptions...).
Value(&wizard.Provider),
huh.NewInput().
Title("Plan/Size").
Description("Enter the plan/size for the server (e.g., s-4vcpu-8gb, e2-standard-2)").
Value(&wizard.Plan).
Validate(requiredValidator),
huh.NewInput().
Title("Region/Datacenter").
Description("Enter the region/datacenter (e.g., fra1, europe-west6-a)").
Value(&wizard.Region).
Validate(requiredValidator),
)
// Group 2: SSH configuration
sshGroup := huh.NewGroup(
huh.NewInput().
Title("SSH Public Key Path").
Description("Enter the full path to your SSH public key (e.g., /home/user/.ssh/id_rsa.pub)").
Value(&wizard.SSH).
Validate(requiredValidator),
huh.NewInput().
Title("SSH Port").
Description("Enter the SSH port").
Value(&wizard.SSHPort).
Validate(portValidator),
)
// Group 3: Security (fail2ban)
securityGroup := huh.NewGroup(
huh.NewInput().
Title("Fail2ban Ban Time").
Description("Enter the fail2ban ban time in seconds").
Value(&wizard.BanTime).
Validate(requiredValidator),
huh.NewInput().
Title("Fail2ban Max Retry").
Description("Enter the fail2ban max retry count").
Value(&wizard.MaxRetry).
Validate(requiredValidator),
)
// Group 4: Features and edition selection
featuresGroup := huh.NewGroup(
huh.NewMultiSelect[string]().
Title("Additional Features").
Description("Select additional features for your server").
Options(featureOptions...).
Value(&features),
huh.NewSelect[string]().
Title("Minecraft Edition").
Description("Select a Minecraft edition").
Options(editionOptions...).
Value(&wizard.Edition),
)
// Group 5: Java configuration (hidden for Bedrock-based editions)
javaGroup := huh.NewGroup(
huh.NewSelect[string]().
Title("Java Version").
Description("Choose the Java version").
Options(javaVersionOptions...).
Value(&wizard.Java),
huh.NewInput().
Title("Java Heap Size").
Description("Enter the Java heap size (rule of thumb: half of available RAM)").
Value(&wizard.Heap).
Validate(heapValidator),
huh.NewInput().
Title("RCON Password").
Description("Enter a RCON password (if you selected that feature)").
Value(&wizard.RconPw),
).WithHideFunc(func() bool {
return isBedrockEdition(wizard.Edition)
})
// Group 6: Minecraft version and properties
minecraftGroup := huh.NewGroup(
huh.NewInput().
Title("Minecraft Version").
Description("Enter the Minecraft version number").
Value(&wizard.Version).
Validate(requiredValidator),
huh.NewText().
Title("Additional Properties").
Description("Add additional Minecraft server properties (key=value, one per line)").
Value(&wizard.Properties).
CharLimit(1000),
)
// Create the form
form := huh.NewForm(
basicGroup,
sshGroup,
securityGroup,
featuresGroup,
javaGroup,
minecraftGroup,
)
// Run the form with headless support
err := ui.RunForm(form, headless)
if err != nil {
return err
}
// Set features
wizard.Features = features
config, err := template.NewTemplateConfig(wizard)
if err != nil {
return err
}
outputFolder := GetHomeFolder()
output, err := cmd.Flags().GetString("output")
if err == nil {
if output != "" {
outputFolder = output
}
}
filename := fmt.Sprintf("%s/config-%s.yaml", outputFolder, wizard.Name)
minectlUI.Info("Writing configuration file to " + filename)
err = os.WriteFile(filename, []byte(config), 0o600)
if err != nil {
return err
}
minectlUI.Info("To create the server:\n\n minectl create -f " + filename)
return nil
}
================================================
FILE: config/bedrock/server-akamai.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server-be
spec:
server:
cloud: akamai
region: eu-central
size: g6-standard-4
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 19132
minecraft:
edition: bedrock
version: 1.26.0.2
eula: true
properties: |
server-name=Akamai Connected Cloud Minecraft
gamemode=survival
force-gamemode=false
difficulty=normal
allow-cheats=false
max-players=100
online-mode=true
white-list=false
server-portv6=19133
view-distance=32
tick-distance=4
player-idle-timeout=30
max-threads=8
level-name=Bedrock level
level-seed=
default-player-permission-level=member
texturepack-required=false
content-log-file-enabled=false
compression-threshold=1
server-authoritative-movement=server-auth
player-movement-score-threshold=20
player-movement-distance-threshold=0.3
player-movement-duration-threshold-in-ms=500
correct-player-movement=false
server-authoritative-block-breaking=false
================================================
FILE: config/bedrock/server-aws.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server-be
spec:
server:
cloud: aws
region: eu-central-1
size: t3.xlarge
ssh:
port: 22
publickeyfile: "/root/.ssh/id_rsa.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 19132
minecraft:
edition: bedrock
version: 1.26.0.2
eula: true
properties: |
server-name=Azure Minecraft - Bedrock edition
gamemode=survival
force-gamemode=false
difficulty=normal
allow-cheats=false
max-players=100
online-mode=true
white-list=false
server-portv6=19133
view-distance=32
tick-distance=4
player-idle-timeout=30
max-threads=8
level-name=Bedrock level
level-seed=
default-player-permission-level=member
texturepack-required=false
content-log-file-enabled=false
compression-threshold=1
server-authoritative-movement=server-auth
player-movement-score-threshold=20
player-movement-distance-threshold=0.3
player-movement-duration-threshold-in-ms=500
correct-player-movement=false
server-authoritative-block-breaking=false
================================================
FILE: config/bedrock/server-civo.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server-be
spec:
server:
cloud: civo
region: LON1
size: g3.large
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft-be.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 19132
minecraft:
edition: bedrock
version: 1.26.0.2
eula: true
properties: |
server-name=Civo Minecraft - Bedrock edition
gamemode=survival
force-gamemode=false
difficulty=normal
allow-cheats=false
max-players=100
online-mode=true
white-list=false
server-portv6=19133
view-distance=32
tick-distance=4
player-idle-timeout=30
max-threads=8
level-name=Bedrock level
level-seed=
default-player-permission-level=member
texturepack-required=false
content-log-file-enabled=false
compression-threshold=1
server-authoritative-movement=server-auth
player-movement-score-threshold=20
player-movement-distance-threshold=0.3
player-movement-duration-threshold-in-ms=500
correct-player-movement=false
server-authoritative-block-breaking=false
================================================
FILE: config/bedrock/server-do.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server-be
spec:
server:
cloud: do
region: fra1
size: s-4vcpu-8gb
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft-be.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 19132
minecraft:
edition: bedrock
version: 1.26.0.2
eula: true
properties: |
server-name=DigitalOcean Minecraft
gamemode=survival
force-gamemode=false
difficulty=normal
allow-cheats=false
max-players=100
online-mode=true
white-list=false
server-portv6=19133
view-distance=32
tick-distance=4
player-idle-timeout=30
max-threads=8
level-name=Bedrock level
level-seed=
default-player-permission-level=member
texturepack-required=false
content-log-file-enabled=false
compression-threshold=1
server-authoritative-movement=server-auth
player-movement-score-threshold=20
player-movement-distance-threshold=0.3
player-movement-duration-threshold-in-ms=500
correct-player-movement=false
server-authoritative-block-breaking=false
================================================
FILE: config/bedrock/server-exoscale.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server-be
spec:
server:
cloud: exoscale
region: de-fra-1
size: medium
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft-be.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 19132
minecraft:
edition: bedrock
version: 1.26.0.2
eula: true
properties: |
server-name=Exoscale Minecraft
gamemode=survival
force-gamemode=false
difficulty=normal
allow-cheats=false
max-players=100
online-mode=true
white-list=false
server-portv6=19133
view-distance=32
tick-distance=4
player-idle-timeout=30
max-threads=8
level-name=Bedrock level
level-seed=
default-player-permission-level=member
texturepack-required=false
content-log-file-enabled=false
compression-threshold=1
server-authoritative-movement=server-auth
player-movement-score-threshold=20
player-movement-distance-threshold=0.3
player-movement-duration-threshold-in-ms=500
correct-player-movement=false
server-authoritative-block-breaking=false
================================================
FILE: config/bedrock/server-gce.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server-be
spec:
server:
cloud: gce
region: europe-west6-a
size: e2-standard-2
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft-be.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 19132
minecraft:
edition: bedrock
version: 1.26.0.2
eula: true
properties: |
server-name=GCE Minecraft
gamemode=survival
force-gamemode=false
difficulty=normal
allow-cheats=false
max-players=100
online-mode=true
white-list=false
server-portv6=19133
view-distance=32
tick-distance=4
player-idle-timeout=30
max-threads=8
level-name=Bedrock level
level-seed=
default-player-permission-level=member
texturepack-required=false
content-log-file-enabled=false
compression-threshold=1
server-authoritative-movement=server-auth
player-movement-score-threshold=20
player-movement-distance-threshold=0.3
player-movement-duration-threshold-in-ms=500
correct-player-movement=false
server-authoritative-block-breaking=false
================================================
FILE: config/bedrock/server-hetzner.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server-be
spec:
server:
cloud: hetzner
region: nbg1
size: cpx31
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft-be.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 19132
minecraft:
edition: bedrock
version: 1.26.0.2
eula: true
properties: |
server-name=Hetzner Minecraft
gamemode=survival
force-gamemode=false
difficulty=normal
allow-cheats=false
max-players=100
online-mode=true
white-list=false
server-portv6=19133
view-distance=32
tick-distance=4
player-idle-timeout=30
max-threads=8
level-name=Bedrock level
level-seed=
default-player-permission-level=member
texturepack-required=false
content-log-file-enabled=false
compression-threshold=1
server-authoritative-movement=server-auth
player-movement-score-threshold=20
player-movement-distance-threshold=0.3
player-movement-duration-threshold-in-ms=500
correct-player-movement=false
server-authoritative-block-breaking=false
================================================
FILE: config/bedrock/server-oci.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server-be
spec:
server:
cloud: oci
region: eu-frankfurt-1
size: VM.Standard2.2
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft-be.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 19132
minecraft:
edition: bedrock
version: 1.26.0.2
eula: true
properties: |
server-name=Civo Minecraft
gamemode=survival
force-gamemode=false
difficulty=normal
allow-cheats=false
max-players=100
online-mode=true
white-list=false
server-portv6=19133
view-distance=32
tick-distance=4
player-idle-timeout=30
max-threads=8
level-name=Bedrock level
level-seed=
default-player-permission-level=member
texturepack-required=false
content-log-file-enabled=false
compression-threshold=1
server-authoritative-movement=server-auth
player-movement-score-threshold=20
player-movement-distance-threshold=0.3
player-movement-duration-threshold-in-ms=500
correct-player-movement=false
server-authoritative-block-breaking=false
================================================
FILE: config/bedrock/server-ovh.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server-be
spec:
server:
cloud: ovh
region: DE1
size: b2-7
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft-be.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 19132
minecraft:
edition: bedrock
version: 1.26.0.2
eula: true
properties: |
server-name=OVHcloud Minecraft
gamemode=survival
force-gamemode=false
difficulty=normal
allow-cheats=false
max-players=100
online-mode=true
white-list=false
server-portv6=19133
view-distance=32
tick-distance=4
player-idle-timeout=30
max-threads=8
level-name=Bedrock level
level-seed=
default-player-permission-level=member
texturepack-required=false
content-log-file-enabled=false
compression-threshold=1
server-authoritative-movement=server-auth
player-movement-score-threshold=20
player-movement-distance-threshold=0.3
player-movement-duration-threshold-in-ms=500
correct-player-movement=false
server-authoritative-block-breaking=false
================================================
FILE: config/bedrock/server-scaleway.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server-bedrock
spec:
server:
cloud: scaleway
region: fr-par-1
size: GP1-XS
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft-be.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 19132
minecraft:
edition: bedrock
version: 1.26.0.2
eula: true
properties: |
server-name=Scaleway Minecraft
gamemode=survival
force-gamemode=false
difficulty=normal
allow-cheats=false
max-players=100
online-mode=true
white-list=false
server-portv6=19133
view-distance=32
tick-distance=4
player-idle-timeout=30
max-threads=8
level-name=Bedrock level
level-seed=
default-player-permission-level=member
texturepack-required=false
content-log-file-enabled=false
compression-threshold=1
server-authoritative-movement=server-auth
player-movement-score-threshold=20
player-movement-distance-threshold=0.3
player-movement-duration-threshold-in-ms=500
correct-player-movement=false
server-authoritative-block-breaking=false
================================================
FILE: config/bedrock/server-vexxhost.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server-bedrock
spec:
server:
cloud: vexxhost
region: am1
size: "v3-starter-2"
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft-be.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 19132
minecraft:
edition: bedrock
version: 1.26.0.2
eula: true
properties: |
server-name=VEXXHOST Minecraft
gamemode=survival
force-gamemode=false
difficulty=normal
allow-cheats=false
max-players=100
online-mode=true
white-list=false
server-portv6=19133
view-distance=32
tick-distance=4
player-idle-timeout=30
max-threads=8
level-name=Bedrock level
level-seed=
default-player-permission-level=member
texturepack-required=false
content-log-file-enabled=false
compression-threshold=1
server-authoritative-movement=server-auth
player-movement-score-threshold=20
player-movement-distance-threshold=0.3
player-movement-duration-threshold-in-ms=500
correct-player-movement=false
server-authoritative-block-breaking=false
================================================
FILE: config/bungeecord/proxy-civo.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftProxy
metadata:
name: minecraft-proxy
spec:
server:
cloud: civo
region: LON1
size: g3.xsmall
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25577
proxy:
java:
openjdk: 8
xmx: 512M
xms: 512M
rcon:
password: test
port: 25575
enabled: true
broadcast: true
type: bungeecord
version: "1.21"
================================================
FILE: config/bungeecord/proxy-do.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftProxy
metadata:
name: minecraft-proxy
spec:
server:
cloud: do
region: fra1
size: s-1vcpu-1gb
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25577
proxy:
java:
openjdk: 8
xmx: 512M
xms: 512M
rcon:
password: test
port: 25575
enabled: true
broadcast: true
type: bungeecord
version: "1.21"
================================================
FILE: config/bungeecord/proxy-vultr.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftProxy
metadata:
name: minecraft-proxy
spec:
server:
cloud: vultr
region: fra
size: "vc2-1c-1gb"
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25577
proxy:
java:
openjdk: 8
xmx: 512M
xms: 512M
rcon:
password: test
port: 25575
enabled: true
broadcast: true
type: bungeecord
version: "1.21"
================================================
FILE: config/craftbukkit/server-akamai.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: akamai
region: eu-central
size: g6-standard-4
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: craftbukkit
version: 1.21.11
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7aAkamai Connected Cloud \u00A7rMinecraft --- \u00A76CraftBukkit \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
================================================
FILE: config/craftbukkit/server-do.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: do
region: fra1
size: s-4vcpu-8gb
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: craftbukkit
version: 1.21.11
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bDigitalOcean \u00A7rMinecraft --- \u00A76CraftBukkit \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/fabric/server-akamai.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: akamai
region: eu-central
size: g6-standard-4
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: fabric
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7aAkamai Connected Cloud \u00A7rMinecraft --- \u00A76Fabric \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
================================================
FILE: config/fabric/server-civo.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: civo
region: LON1
size: g3.large
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: fabric
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bCivo \u00A7rMinecraft --- \u00A76Fabric \u00A7redition
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/fabric/server-do.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: do
region: fra1
size: s-4vcpu-8gb
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: fabric
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bDigitalOcean \u00A7rMinecraft --- \u00A76Fabric \u00A7redition
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/forge/server-akamai.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: akamai
region: eu-central
size: g6-standard-4
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: forge
version: 1.21.11-61.1.1
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7aAkamai Connected Cloud \u00A7rMinecraft --- \u00A76Forge \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
================================================
FILE: config/forge/server-civo.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: civo
region: LON1
size: g3.large
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: forge
version: 1.21.11-61.1.1
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bCivo \u00A7rMinecraft --- \u00A76Forge \u00A7redition
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/forge/server-do.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
monitoring:
enabled: true
server:
cloud: do
region: fra1
size: s-4vcpu-8gb
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: forge
version: 1.21.11-61.1.1
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bDigitalOcean \u00A7rMinecraft --- \u00A76Forge \u00A7redition
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/java/server-akamai.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: akamai
region: eu-central
size: g6-standard-4
ssh:
port: 2223
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7aAkamai Connected Cloud \u00A7rMinecraft --- \u00A76Java \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
================================================
FILE: config/java/server-aws-arm.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server-arm
spec:
monitoring:
enabled: false
server:
cloud: aws
region: eu-central-1
size: c6g.xlarge
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
arm: true
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A76AWS Arm \u00A7rMinecraft --- \u00A76Java \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
================================================
FILE: config/java/server-aws-spot.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server-spot
spec:
monitoring:
enabled: false
server:
cloud: aws
region: eu-central-1
size: t3.xlarge
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
spot: true
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A76AWS Spot \u00A7rMinecraft --- \u00A76Java \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
================================================
FILE: config/java/server-aws.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
monitoring:
enabled: false
server:
cloud: aws
region: eu-central-1
size: t3.xlarge
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: "1.21.11"
eula: true
properties: |
allow-flight=false
allow-nether=true
broadcast-console-to-ops=true
broadcast-rcon-to-ops=true
difficulty=easy
enable-command-block=false
enable-jmx-monitoring=false
enable-query=false
enable-rcon=false
enable-status=true
enforce-secure-profile=true
enforce-whitelist=false
entity-broadcast-range-percentage=100
force-gamemode=false
function-permission-level=2
gamemode=survival
generate-structures=true
generator-settings={}
hardcore=false
hide-online-players=false
level-name=world
level-seed=minectlrocks
level-type=minecraft\:normal
max-chained-neighbor-updates=1000000
max-players=20
max-tick-time=60000
max-world-size=29999984
motd=\u00A76AWS \u00A7rMinecraft --- \u00A76Java \u00A7redition
network-compression-threshold=256
online-mode=true
op-permission-level=4
player-idle-timeout=0
prevent-proxy-connections=false
previews-chat=false
pvp=true
query.port=25565
rate-limit=0
rcon.password=
rcon.port=25575
require-resource-pack=false
resource-pack=
resource-pack-prompt=
resource-pack-sha1=
server-ip=
server-port=25565
simulation-distance=10
spawn-animals=true
spawn-monsters=true
spawn-npcs=true
spawn-protection=16
sync-chunk-writes=true
text-filtering-config=
use-native-transport=true
view-distance=10
white-list=false
================================================
FILE: config/java/server-azure-spot.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: azure
region: westeurope
size: Standard_D2_v4
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
spot: true
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bAzure Spot \u00A7rMinecraft --- \u00A76Java \u00A7redition
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/java/server-azure.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: azure
region: westeurope
size: Standard_D2_v4
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bAzure \u00A7rMinecraft --- \u00A76Java \u00A7redition
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/java/server-civo.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: civo
region: LON1
size: g3.large
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival25565
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bCivo \u00A7rMinecraft --- \u00A76Java \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
================================================
FILE: config/java/server-do.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: do
region: fra1
size: s-4vcpu-8gb
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bDigitalOcean \u00A7rMinecraft --- \u00A76Java \u00A7redition
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/java/server-exoscale.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: exoscale
region: de-fra-1
size: medium
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival25565
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7cExoscale \u00A7rMinecraft --- \u00A76Java \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
================================================
FILE: config/java/server-fuga.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
monitoring:
enabled: false
server:
cloud: fuga
region: ams2
size: s3.large
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A76Fuga Cloud \u00A7rMinecraft --- \u00A76Java \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
================================================
FILE: config/java/server-gce-arm.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server-arm
spec:
server:
cloud: gce
region: europe-west4-a
size: t2a-standard-2
ssh:
port: 2223
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
arm: true
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A79GCE ARM \u00A7rMinecraft --- \u00A76Java \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
================================================
FILE: config/java/server-gce-spot.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: gce
region: europe-west6-a
size: e2-standard-2
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
spot: true
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A79GCE \u00A7rMinecraft --- \u00A76Java \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
================================================
FILE: config/java/server-gce.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: gce
region: europe-west6-a
size: e2-standard-2
ssh:
port: 2223
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A79GCE \u00A7rMinecraft --- \u00A76Java \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
================================================
FILE: config/java/server-hetzner-arm.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: hetzner
region: fsn1
size: cax21
arm: true
ssh:
port: 2223
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7cHetzner Arm \u00A7rMinecraft --- \u00A76Java \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/java/server-hetzner.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: hetzner
region: nbg1
size: cpx31
ssh:
port: 2223
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7cHetzner \u00A7rMinecraft --- \u00A76Java \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/java/server-oci.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: oci
region: eu-frankfurt-1
size: VM.Standard2.2
ssh:
port: 2223
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bOracle Cloud Infrastructure \u00A7rMinecraft --- \u00A76Java \u00A7reditio
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
================================================
FILE: config/java/server-ovh.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: ovh
region: DE1
size: b2-7
ssh:
port: 2223
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7cOVHcloud \u00A7rMinecraft --- \u00A76Java \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
================================================
FILE: config/java/server-scaleway.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
monitoring:
enabled: true
server:
cloud: scaleway
region: fr-par-1
size: GP1-XS
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7cScaleway \u00A7rMinecraft --- \u00A76Java \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
================================================
FILE: config/java/server-vexxhost.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: vexxhost
region: am1
size: "v3-starter-2"
ssh:
port: 2223
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival25565
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A75VEXXHOST \u00A7rMinecraft --- \u00A76Java \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
================================================
FILE: config/java/server-vultr.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: vultr
region: fra
size: "vc2-2c-4gb"
ssh:
port: 2223
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival25565
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bVultr \u00A7rMinecraft --- \u00A76Java \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
================================================
FILE: config/multipass/server-java.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: multipass
port: 25565
size: 1-4G
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A76Multipass \u00A7rMinecraft --- \u00A76Java \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/multipass/server-papermc.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: multipass
port: 25565
size: 1-4G
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: papermc
version: 1.21.11-117
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A76Multipass \u00A7rMinecraft --- \u00A76PaperMC \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/nukkit/server-azure.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: azure
region: westeurope
size: Standard_D2_v4
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 19132
minecraft:
java:
openjdk: 8
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: nukkit
version: 1.0-SNAPSHOT
eula: true
properties: |
motd=Azure Minecraft --- Nukkitx edition
sub-motd=https://nukkitx.com
server-ip=0.0.0.0
view-distance=10
white-list=off
achievements=on
announce-player-achievements=on
spawn-protection=16
max-players=20
allow-flight=off
spawn-animals=on
spawn-mobs=on
gamemode=0
force-gamemode=off
hardcore=off
pvp=on
difficulty=1
generator-settings=
level-name=world
level-seed=
level-type=DEFAULT
allow-nether=on
enable-query=on
auto-save=on
force-resources=off
xbox-auth=on
================================================
FILE: config/nukkit/server-civo.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: civo
region: LON1
size: g3.large
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 19132
minecraft:
java:
openjdk: 8
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: nukkit
version: 1.0-SNAPSHOT
eula: true
properties: |
motd=Civo Minecraft --- Nukkitx edition
sub-motd=https://nukkitx.com
server-ip=0.0.0.0
view-distance=10
white-list=off
achievements=on
announce-player-achievements=on
spawn-protection=16
max-players=20
allow-flight=off
spawn-animals=on
spawn-mobs=on
gamemode=0
force-gamemode=off
hardcore=off
pvp=on
difficulty=1
generator-settings=
level-name=world
level-seed=
level-type=DEFAULT
allow-nether=on
enable-query=on
auto-save=on
force-resources=off
xbox-auth=on
================================================
FILE: config/nukkit/server-do.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: do
region: fra1
size: s-4vcpu-8gb
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 19132
minecraft:
java:
openjdk: 8
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: nukkit
version: 1.0-SNAPSHOT
eula: true
properties: |
motd=DigitalOcean Minecraft --- Nukkitx edition
sub-motd=https://nukkitx.com
server-ip=0.0.0.0
view-distance=10
white-list=off
achievements=on
announce-player-achievements=on
spawn-protection=16
max-players=20
allow-flight=off
spawn-animals=on
spawn-mobs=on
gamemode=0
force-gamemode=off
hardcore=off
pvp=on
difficulty=1
generator-settings=
level-name=world
level-seed=
level-type=DEFAULT
allow-nether=on
enable-query=on
auto-save=on
force-resources=off
xbox-auth=on
================================================
FILE: config/nukkit/server-fuga.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: fuga
region: ams2
size: s3.large
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 19132
minecraft:
java:
openjdk: 8
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: nukkit
version: 1.0-SNAPSHOT
eula: true
properties: |
motd=Fuga Cloud Minecraft --- Nukkitx edition
sub-motd=https://nukkitx.com
server-ip=0.0.0.0
view-distance=10
white-list=off
achievements=on
announce-player-achievements=on
spawn-protection=16
max-players=20
allow-flight=off
spawn-animals=on
spawn-mobs=on
gamemode=0
force-gamemode=off
hardcore=off
pvp=on
difficulty=1
generator-settings=
level-name=world
level-seed=
level-type=DEFAULT
allow-nether=on
enable-query=on
auto-save=on
force-resources=off
xbox-auth=on
================================================
FILE: config/nukkit/server-gce.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: gce
region: europe-west6-a
size: e2-standard-2
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 19132
minecraft:
java:
openjdk: 8
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: nukkit
version: 1.0-SNAPSHOT
eula: true
properties: |
motd=GCE Minecraft --- Nukkitx edition
sub-motd=https://nukkitx.com
server-ip=0.0.0.0
view-distance=10
white-list=off
achievements=on
announce-player-achievements=on
spawn-protection=16
max-players=20
allow-flight=off
spawn-animals=on
spawn-mobs=on
gamemode=0
force-gamemode=off
hardcore=off
pvp=on
difficulty=1
generator-settings=
level-name=world
level-seed=
level-type=DEFAULT
allow-nether=on
enable-query=on
auto-save=on
force-resources=off
xbox-auth=on
================================================
FILE: config/nukkit/server-ovh.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: ovh
region: DE1
size: b2-7
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 19132
minecraft:
java:
openjdk: 8
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: nukkit
version: 1.0-SNAPSHOT
eula: true
properties: |
motd=GCE Minecraft --- Nukkitx edition
sub-motd=https://nukkitx.com
server-ip=0.0.0.0
view-distance=10
white-list=off
achievements=on
announce-player-achievements=on
spawn-protection=16
max-players=20
allow-flight=off
spawn-animals=on
spawn-mobs=on
gamemode=0
force-gamemode=off
hardcore=off
pvp=on
difficulty=1
generator-settings=
level-name=world
level-seed=
level-type=DEFAULT
allow-nether=on
enable-query=on
auto-save=on
force-resources=off
xbox-auth=on
================================================
FILE: config/papermc/server-akamai.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: akamai
region: eu-central
size: g6-standard-4
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: papermc
version: 1.21.11-117
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7aAkamai Connected Cloud \u00A7rMinecraft --- \u00A76PaperMC \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
================================================
FILE: config/papermc/server-aws-arm.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server-arm
spec:
server:
cloud: aws
region: eu-central-1
size: c6g.xlarge
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
arm: true
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: papermc
version: 1.21.11-117
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A76AWS \u00A7rMinecraft Graviton --- \u00A76PaperMC \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/papermc/server-aws.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: aws
region: eu-central-1
size: t3.xlarge
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: papermc
version: 1.21.11-117
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A76AWS \u00A7rMinecraft --- \u00A76PaperMC \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/papermc/server-azure-arm.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server-arm
spec:
server:
cloud: azure
region: westeurope
size: Standard_D2ps_v5
ssh:
port: 2223
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
arm: true
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: papermc
version: 1.21.11-117
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bAzure ARM \u00A7rMinecraft --- \u00A76PaperMC \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/papermc/server-azure.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: azure
region: westeurope
size: Standard_D2_v4
ssh:
port: 2223
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: papermc
version: 1.21.11-117
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bAzure \u00A7rMinecraft --- \u00A76PaperMC \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/papermc/server-civo.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
monitoring:
enabled: true
server:
cloud: civo
region: LON1
size: g3.large
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: papermc
version: 1.21.11-117
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bCivo \u00A7rMinecraft --- \u00A76PaperMC \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
================================================
FILE: config/papermc/server-do.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
monitoring:
enabled: true
server:
cloud: do
region: fra1
size: s-4vcpu-8gb
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: papermc
version: 1.21.11-117
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bDigitalOcean \u00A7rMinecraft --- \u00A76PaperMC \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/papermc/server-exoscale.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: exoscale
region: de-fra-1
size: medium
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: papermc
version: 1.21.11-117
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7cExoscale \u00A7rMinecraft --- \u00A76Java \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/papermc/server-fuga.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: fuga
region: ams2
size: s3.large
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: papermc
version: 1.21.11-117
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A75Fuga Cloud \u00A7rMinecraft --- \u00A76PaperMC \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/papermc/server-gce-arm.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server-arm
spec:
server:
cloud: gce
region: europe-west4-a
size: t2a-standard-2
ssh:
port: 2223
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
arm: true
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: papermc
version: 1.21.11-117
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A79GCE ARM \u00A7rMinecraft --- \u00A76PaperMC \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/papermc/server-hetzner.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: hetzner
region: nbg1
size: cpx31
ssh:
port: 2223
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: papermc
version: 1.21.11-117
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7cHetzner \u00A7rMinecraft --- \u00A76PaperMC \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/papermc/server-oci-arm.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server-arm
spec:
monitoring:
enabled: true
server:
cloud: oci
region: eu-frankfurt-1
size: VM.Standard.A1.Flex
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
arm: true
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: papermc
version: 1.21.11-117
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bOracle Cloud Infrastructure \u00A7rMinecraft --- \u00A76PaperMC \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/papermc/server-oci.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
monitoring:
enabled: true
server:
cloud: oci
region: eu-frankfurt-1
size: VM.Standard2.2
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: papermc
version: 1.21.11-117
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bOracle Cloud Infrastructure \u00A7rMinecraft --- \u00A76PaperMC \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/papermc/server-scaleway.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
monitoring:
enabled: true
server:
cloud: scaleway
region: fr-par-1
size: DEV1-M
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: papermc
version: 1.21.11-117
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7cScaleway \u00A7rMinecraft --- \u00A76PaperMC \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=20
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/papermc/server-vexxhost.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: vexxhost
region: am1
size: "v3-starter-2"
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: papermc
version: 1.21.11-117
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A75VEXXHOST \u00A7rMinecraft --- \u00A76PaperMC \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/papermc/server-vultr.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
monitoring:
enabled: true
server:
cloud: vultr
region: fra
size: "vc2-2c-4gb"
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: papermc
version: 1.21.11-117
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bVultr \u00A7rMinecraft --- \u00A76PaperMC \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/powernukkit/server-azure.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: azure
region: westeurope
size: Standard_D2_v4
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 19132
minecraft:
java:
openjdk: 8
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: powernukkit
version: 1.6.0.1-PN
eula: true
properties: |
motd=Azure Minecraft --- Nukkitx edition
sub-motd=https://nukkitx.com
server-ip=0.0.0.0
view-distance=10
white-list=off
achievements=on
announce-player-achievements=on
spawn-protection=16
max-players=20
allow-flight=off
spawn-animals=on
spawn-mobs=on
gamemode=0
force-gamemode=off
hardcore=off
pvp=on
difficulty=1
generator-settings=
level-name=world
level-seed=
level-type=DEFAULT
allow-nether=on
enable-query=on
auto-save=on
force-resources=off
xbox-auth=on
================================================
FILE: config/powernukkit/server-civo.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: civo
region: LON1
size: g3.large
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 19132
minecraft:
java:
openjdk: 8
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: powernukkit
version: 1.6.0.1-PN
eula: true
properties: |
motd=Azure Minecraft --- Nukkitx edition
sub-motd=https://nukkitx.com
server-ip=0.0.0.0
view-distance=10
white-list=off
achievements=on
announce-player-achievements=on
spawn-protection=16
max-players=20
allow-flight=off
spawn-animals=on
spawn-mobs=on
gamemode=0
force-gamemode=off
hardcore=off
pvp=on
difficulty=1
generator-settings=
level-name=world
level-seed=
level-type=DEFAULT
allow-nether=on
enable-query=on
auto-save=on
force-resources=off
xbox-auth=on
================================================
FILE: config/purpur/server-akamai.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: akamai
region: eu-central
size: g6-standard-4
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: purpur
version: 1.21.11-2553
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7aAkamai Connected Cloud \u00A7rMinecraft --- \u00A76Purpur \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
================================================
FILE: config/purpur/server-aws-arm.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server-arm
spec:
server:
cloud: aws
region: eu-central-1
size: c6g.xlarge
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
arm: true
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: purpur
version: 1.21.11-2553
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A76AWS \u00A7rMinecraft Graviton --- \u00A76Purpur \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/purpur/server-aws.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: aws
region: eu-central-1
size: t3.xlarge
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: purpur
version: 1.21.11-2553
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A76AWS \u00A7rMinecraft --- \u00A76Purpur \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/purpur/server-azure-arm.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server-arm
spec:
server:
cloud: azure
region: westeurope
size: Standard_D2ps_v5
ssh:
port: 2223
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
arm: true
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: purpur
version: 1.21.11-2553
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bAzure ARM \u00A7rMinecraft --- \u00A76Purpur \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/purpur/server-azure.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: azure
region: westeurope
size: Standard_D2_v4
ssh:
port: 2223
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: purpur
version: 1.21.11-2553
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bAzure \u00A7rMinecraft --- \u00A76Purpur \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/purpur/server-civo.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
monitoring:
enabled: true
server:
cloud: civo
region: LON1
size: g3.large
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: purpur
version: 1.21.11-2553
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bCivo \u00A7rMinecraft --- \u00A76Purpur \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
================================================
FILE: config/purpur/server-do.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
monitoring:
enabled: true
server:
cloud: do
region: fra1
size: s-4vcpu-8gb
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: purpur
version: 1.21.11-2553
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bDigitalOcean \u00A7rMinecraft --- \u00A76Purpur \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/purpur/server-exoscale.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: exoscale
region: de-fra-1
size: medium
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: purpur
version: 1.21.11-2553
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7cExoscale \u00A7rMinecraft --- \u00A76Java \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/purpur/server-fuga.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: fuga
region: ams2
size: s3.large
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: purpur
version: 1.21.11-2553
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A75Fuga Cloud \u00A7rMinecraft --- \u00A76Purpur \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/purpur/server-gce-arm.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server-arm
spec:
server:
cloud: gce
region: europe-west4-a
size: t2a-standard-2
ssh:
port: 2223
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
arm: true
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: purpur
version: 1.21.11-2553
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A79GCE ARM \u00A7rMinecraft --- \u00A76Purpur \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/purpur/server-hetzner.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: hetzner
region: nbg1
size: cpx31
ssh:
port: 2223
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: purpur
version: 1.21.11-2553
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7cHetzner \u00A7rMinecraft --- \u00A76Purpur \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/purpur/server-oci-arm.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server-arm
spec:
monitoring:
enabled: true
server:
cloud: oci
region: eu-frankfurt-1
size: VM.Standard.A1.Flex
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
arm: true
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: purpur
version: 1.21.11-2553
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bOracle Cloud Infrastructure \u00A7rMinecraft --- \u00A76Purpur \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/purpur/server-oci.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
monitoring:
enabled: true
server:
cloud: oci
region: eu-frankfurt-1
size: VM.Standard2.2
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: purpur
version: 1.21.11-2553
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bOracle Cloud Infrastructure \u00A7rMinecraft --- \u00A76Purpur \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/purpur/server-scaleway.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
monitoring:
enabled: true
server:
cloud: scaleway
region: fr-par-1
size: DEV1-M
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: purpur
version: 1.21.11-2553
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7cScaleway \u00A7rMinecraft --- \u00A76Purpur \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=20
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/purpur/server-vexxhost.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: vexxhost
region: am1
size: "v3-starter-2"
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: purpur
version: 1.21.11-2553
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A75VEXXHOST \u00A7rMinecraft --- \u00A76Purpur \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/purpur/server-vultr.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
monitoring:
enabled: true
server:
cloud: vultr
region: fra
size: "vc2-2c-4gb"
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: purpur
version: 1.21.11-2553
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bVultr \u00A7rMinecraft --- \u00A76Purpur \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/spigot/server-akamai.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: akamai
region: eu-central
size: g6-standard-4
volumeSize: 100
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: spigot
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7aAkamai Connected Cloud \u00A7rMinecraft --- \u00A76Spigot \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
================================================
FILE: config/spigot/server-azure.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: azure
region: westeurope
size: Standard_D2_v4
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: spigot
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bAzure \u00A7rMinecraft --- \u00A76Spigot \u00A7redition
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/spigot/server-do.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: do
region: fra1
size: s-4vcpu-8gb
volumeSize: 100
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: spigot
version: "1.21.11"
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00A7bDigitalOcean \u00A7rMinecraft --- \u00A76Spigot \u00A7redition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=
================================================
FILE: config/velocity/proxy-do.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftProxy
metadata:
name: minecraft-proxy
spec:
server:
cloud: do
region: fra1
size: s-1vcpu-1gb
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25577
proxy:
java:
openjdk: 16
xmx: 512M
xms: 512M
rcon:
password: test
port: 25575
enabled: true
broadcast: true
type: velocity
version: 3.5.0-SNAPSHOT-576
================================================
FILE: config/velocity/proxy-gce.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftProxy
metadata:
name: minecraft-proxy
spec:
server:
cloud: gce
region: europe-west6-a
size: e2-standard-2
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25577
proxy:
java:
openjdk: 16
xmx: 512M
xms: 512M
type: velocity
version: 3.5.0-SNAPSHOT-576
================================================
FILE: config/waterfall/proxy-azure.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftProxy
metadata:
name: minecraft-proxy
spec:
server:
cloud: azure
region: westeurope
size: Standard_D2_v4
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
security: true
port: 25577
proxy:
java:
openjdk: 8
xmx: 512M
xms: 512M
rcon:
password: test
port: 25575
enabled: true
broadcast: true
type: waterfall
version: 1.21-600
================================================
FILE: config/waterfall/proxy-do.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftProxy
metadata:
name: minecraft-proxy
spec:
server:
cloud: do
region: fra1
size: s-1vcpu-1gb
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25577
proxy:
java:
openjdk: 8
xmx: 512M
xms: 512M
rcon:
password: test
port: 25575
enabled: true
broadcast: true
type: waterfall
version: 1.21-600
================================================
FILE: config/waterfall/proxy-vultr.yaml
================================================
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftProxy
metadata:
name: minecraft-proxy
spec:
server:
cloud: vultr
region: fra
size: "vc2-1c-1gb"
ssh:
port: 22
publickeyfile: "/Users/dirien/Tools/repos/stackit-minecraft/minecraft/ssh/minecraft.pub"
fail2ban:
bantime: 1000
maxretry: 3
port: 25577
proxy:
java:
openjdk: 8
xmx: 512M
xms: 512M
rcon:
password: test
port: 25575
enabled: true
broadcast: true
type: waterfall
version: 1.21-600
================================================
FILE: development.md
================================================
#How to start development on minectl
# Install pre-commit
brew install pre-commit
================================================
FILE: docs/architecture.md
================================================
# minectl 🗺 Architecture diagram
The architecture of minectl is quite straight forward:

With the help of different types of cloud provider implementations, we are able to translate a MinecraftSever or
MinecraftProxy manifest into a running VM instance.
Several Ports where exposed in the is process, where the Server or Proxy port is the minimum. If the User wants to
expose a monitoring on top, he can enable this in the manifest files.
================================================
FILE: docs/authentication.md
================================================
# Authentication
`minectl` is completely built on zero-trust. It does not save any API tokens, instead it looks them up in environment variables.
## Cloud Provider Credentials
### Civo
```bash
export CIVO_TOKEN=xx
```
### DigitalOcean
```bash
export DIGITALOCEAN_TOKEN=xxx
```
### Scaleway
```bash
export ACCESS_KEY=xxx
export SECRET_KEY=yyy
export ORGANISATION_ID=zzz
```
### Hetzner
```bash
export HCLOUD_TOKEN=yyyy
```
### Akamai Connected Cloud
```bash
export LINODE_TOKEN=xxxx
```
### OVHCloud
You need to create API keys per endpoint. For an overview of available endpoints, check the [supported-apis](https://github.com/ovh/go-ovh#supported-apis) documentation.
For example, Europe visit https://eu.api.ovh.com/createToken to create your API keys for `minectl`.

For the proper `rights` choose all HTTP Verbs (GET, PUT, DELETE, POST), and we need only the `/cloud/*` API.
```bash
export OVH_ENDPOINT=ovh-eu
export APPLICATION_KEY=xxx
export APPLICATION_SECRET=yyy
export CONSUMER_KEY=zzz
export SERVICENAME=
```
### Google Compute Engine (GCE)
`minectl` uses Google Cloud's Application Default Credentials (ADC) for authentication. This supports multiple authentication methods:
#### Option 1: Sign in with gcloud CLI (Recommended)
```bash
gcloud auth application-default login
export GOOGLE_PROJECT=
export GOOGLE_SERVICE_ACCOUNT_EMAIL=@.iam.gserviceaccount.com
```
#### Option 2: Service account JSON file
```bash
export GOOGLE_APPLICATION_CREDENTIALS=/service-account.json
export GOOGLE_PROJECT=
export GOOGLE_SERVICE_ACCOUNT_EMAIL=@.iam.gserviceaccount.com
```
#### Required Environment Variables
| Variable | Description |
|----------|-------------|
| `GOOGLE_PROJECT` | Your GCP project ID |
| `GOOGLE_SERVICE_ACCOUNT_EMAIL` | Service account email (required for OS Login SSH access) |
| `GOOGLE_APPLICATION_CREDENTIALS` | (Optional) Path to service account JSON file |
See [Getting Started - GCE edition](getting-started-gce.md) for details on how to create a GCP service account for `minectl`.
### Vultr
```bash
export VULTR_API_KEY=xxx
```
### Azure
> Please select a Hypervisor Generation '2' VM Size. As `minectl` uses only Hypervisor Generation 2 Images.
`minectl` uses Azure's DefaultAzureCredential for authentication, which supports multiple authentication methods automatically.
#### Required Environment Variable
```bash
export AZURE_SUBSCRIPTION_ID=xxx
```
#### Option 1: Sign in with Azure CLI (Recommended)
```bash
az login
export AZURE_SUBSCRIPTION_ID=
```
#### Option 2: Service principal with a secret
```bash
export AZURE_SUBSCRIPTION_ID=""
export AZURE_TENANT_ID=""
export AZURE_CLIENT_ID=""
export AZURE_CLIENT_SECRET=""
```
#### Option 3: Service principal with certificate
```bash
export AZURE_SUBSCRIPTION_ID=""
export AZURE_TENANT_ID=""
export AZURE_CLIENT_ID=""
export AZURE_CLIENT_CERTIFICATE_PATH=""
```
#### Option 4: Username and password
```bash
export AZURE_SUBSCRIPTION_ID=""
export AZURE_CLIENT_ID=""
export AZURE_USERNAME=""
export AZURE_PASSWORD=""
```
#### Option 5: Managed identity (when running on Azure)
```bash
export AZURE_SUBSCRIPTION_ID=""
export AZURE_CLIENT_ID=""
```
See [Azure authentication with the Azure SDK for Go](https://docs.microsoft.com/en-us/azure/developer/go/azure-sdk-authentication) for details.
### Oracle Cloud Infrastructure
The authentication uses OCI config file with the default profile.
Example:
```bash
cat /Users/user/.oci/config
[DEFAULT]
user=
fingerprint=
key_file=
tenancy=
region=
```
Please follow the instructions at https://docs.oracle.com/en-us/iaas/Content/API/Concepts/apisigningkey.htm
### Amazon AWS
`minectl` uses the standard AWS credential chain, which supports multiple authentication methods automatically.
#### Option 1: Sign in with AWS CLI (Recommended)
```bash
aws configure
```
This creates credentials in `~/.aws/credentials` and config in `~/.aws/config`.
#### Option 2: Shared credentials file
The credentials file is located in `~/.aws/credentials`:
```bash
cat ~/.aws/credentials
[default]
aws_access_key_id = xxxx
aws_secret_access_key = zzzz
```
#### Option 3: Environment variables
```bash
export AWS_ACCESS_KEY_ID=
export AWS_SECRET_ACCESS_KEY=
export AWS_REGION=
```
#### Option 4: IAM instance profile (when running on EC2)
When running on EC2, credentials are automatically retrieved from the instance metadata service.
#### Credential Chain Order
`minectl` looks for credentials in the following order:
1. Environment variables
2. Shared credentials file (`~/.aws/credentials`)
3. Shared config file (`~/.aws/config`)
4. IAM instance profile (EC2)
5. Container credentials (ECS/Fargate)
### VEXXHOST
It is recommended to store OpenStack credentials as environment variables because it decouples credential information from source code.
Download the `OpenStack RC File` from the Horizon UI by clicking on the "Download OpenStack RC File" button at the top right-hand corner.
To execute the file, run `source xxxx-openrc.sh` and you will be prompted for your password.
### Multipass
> Set the plan to cpu-memG. For example: `1-2G`
Multipass is a mini-cloud on your workstation using native hypervisors of all the supported platforms (Windows, macOS and Linux). It will give you an Ubuntu command line in just a click ("Open shell") or a simple `multipass shell` command, or even a keyboard shortcut.
Find what images are available with `multipass find` and create new instances with `multipass launch`.
To install multipass, follow the instructions on [multipass.run](https://multipass.run/) for your platform.
### Exoscale
Go to the IAM section in the Exoscale Console and create a new API key. You can restrict the key to just perform operations on the `compute` service.
```bash
export EXOSCALE_API_KEY=
export EXOSCALE_API_SECRET=
```
### Fuga Cloud
To get the `OpenStack RC File` from the Fuga Cloud UI, follow these steps:
1. Log in to the Fuga Cloud Dashboard
2. Go to Account -> Access -> Credentials
3. You can choose a user credential or team credential
4. If you haven't already, you should create one of these credentials. Hold on to the password
5. Click on download OpenRC. This file contains all necessary configurations for the client
```bash
source fuga-openrc.sh
```
Enter the password which matches the username of the contents of the OpenRC file.
================================================
FILE: docs/cli-reference.md
================================================
# CLI Reference
## Global Flags
All commands support these global flags:
```
--headless Run in CI mode with logging enabled and human-readable output disabled (default: false)
--log-encoding string Set the log encoding: console|json (default: "console")
--verbose string Enable verbose logging: debug|info|warn|error|dpanic|panic|fatal
```
## Commands
### wizard
Create a configuration file interactively.
```bash
minectl wizard [flags]
```
**Flags:**
- `-h, --help` - Help for wizard
- `-o, --output string` - Output folder for the configuration file (default: ~/.minectl)
**Example:**
```bash
minectl wizard
```
---
### create
Create a Minecraft Server.
```bash
minectl create [flags]
```
**Flags:**
- `-f, --filename string` - Location of the manifest file
- `-h, --help` - Help for create
- `-w, --wait` - Wait for Minecraft Server to start (default: true)
**Example:**
```bash
minectl create --filename server-do.yaml
```
---
### delete
Delete a Minecraft Server.
```bash
minectl delete [flags]
```
**Flags:**
- `-f, --filename string` - Location of the manifest file
- `-h, --help` - Help for delete
- `--id string` - Contains the server ID
- `-y, --yes` - Automatically delete the server without confirmation
**Example:**
```bash
minectl delete --filename server-do.yaml --id xxx-xxx-xxx-xxx
```
---
### list
List all Minecraft Servers.
```bash
minectl list [flags]
```
**Flags:**
- `-h, --help` - Help for list
- `-p, --provider string` - The cloud provider (civo|scaleway|do|hetzner|akamai|ovh|gce|vultr|azure|oci|aws|vexxhost|fuga|multipass|exoscale)
- `-r, --region string` - The region for your cloud provider
**Example:**
```bash
minectl list --provider civo --region LON1
```
---
### update
Update a Minecraft Server version. Uses SSH (port 22) to connect.
```bash
minectl update [flags]
```
**Flags:**
- `-f, --filename string` - Location of the manifest file
- `-h, --help` - Help for update
- `--id string` - Contains the server ID
- `-k, --ssh-key string` - Specify a specific path for the SSH key
**Example:**
```bash
minectl update --filename server-do.yaml --id xxx-xxx-xxx-xxx
```
---
### rcon
Connect to the RCON port of your Minecraft Server. RCON is a protocol that allows server administrators to remotely execute Minecraft commands.
```bash
minectl rcon [flags]
```
**Flags:**
- `-f, --filename string` - Location of the manifest file
- `-h, --help` - Help for rcon
- `--id string` - Contains the server ID
**Example:**
```bash
minectl rcon --filename server-do.yaml --id xxxx
```
---
### plugins
> This feature is still in beta.
Upload a local plugin file to your server. Uses SSH (port 22) to connect.
```bash
minectl plugins [flags]
```
**Flags:**
- `-d, --destination string` - Plugin destination folder
- `-f, --filename string` - Location of the manifest file
- `-h, --help` - Help for plugins
- `--id string` - Contains the server ID
- `-p, --plugin string` - Location of the plugin
- `-k, --ssh-key string` - Specify a specific path for the SSH key
**Example:**
```bash
minectl plugins \
--filename server-do.yaml \
--id xxx-xxx-xxx-xxx \
--plugin plugin.jar \
--destination /minecraft/mods
```
## Headless Mode
With the global flag `--headless`, you can run `minectl` in a less human-readable output version. This is helpful when running `minectl` in CI/CD workflows.
The `--verbose` flag sets the level of logging and `--log-encoding` lets you choose between `json` and `console` as the encoding format.
**Example:**
```bash
minectl create --filename server.yaml --headless --verbose info --log-encoding json
```
================================================
FILE: docs/colored-motd.md
================================================
# How to colour your server MOTD
```bash
\u00A70 - BLACK
\u00A71 - DARK BLUE
\u00A72 - DARK GREEN
\u00A73 - DARK AQUA
\u00A74 - DARK RED
\u00A75 - DARK PURPLE
\u00A76 - GOLD
\u00A77 - GRAY
\u00A78 - DARK GRAY
\u00A79 - INDIGO
\u00A7a - GREEN
\u00A7b - AQUA
\u00A7c - RED
\u00A7d - PINK
\u00A7e - YELLOW
\u00A7f - WHITE
\u00A7k - Obfuscated
\u00A7l - Bold
\u00A7m - Strikethrough
\u00A7n - Underline
\u00A7o - Italic
\u00A7r - Reset
```
You can use § in replacement instead of \u00A7 if you choose to do so.
================================================
FILE: docs/configuration.md
================================================
# Configuration
`minectl` uses YAML manifest files to describe Minecraft servers and proxies. You can create these manually or use the interactive wizard.
## Configuration Wizard
Use the wizard to create configuration files interactively:
```bash
minectl wizard
```
[](https://asciinema.org/a/439572)
## MinecraftServer Config
You need a MinecraftServer manifest file to describe the underlying compute instance and the Minecraft Server:
```yaml
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
monitoring:
enabled: true|false
server:
cloud: "civo|scaleway|do|hetzner|akamai|ovh|gce|vultr|azure|oci|aws|vexxhost|fuga|multipass|exoscale"
region: "region see cloud provider for details eg. fra1"
size: "see cloud provider docs for details eg. g3.large"
volumeSize: 100
ssh:
port: 22 # or your custom port
publickeyfile: ".pub"
fail2ban:
bantime: ""
maxretry: ""
port: "25565|19132 are the defaults for tcp/udp"
spot: true|false
arm: true|false
minecraft:
java:
openjdk: "8|16 use jdk 8 for <1.17 java server version"
xmx: 2G
xms: 2G
options:
- "-XX:+UseG1GC"
- "-XX:+ParallelRefProcEnabled"
- "-XX:MaxGCPauseMillis=200"
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: "java|bedrock|nukkit|powernukkit|craftbukkit|fabric|forge|papermc|spigot|purpur"
version: ""
eula: true
properties: |
level-seed=minectlrocks
broadcast-rcon-to-ops=true
...
```
> **Attention:** Please lookup the correct service size if you are setting the `arm` attribute to `true`.
Example configs are available in the [config](https://github.com/dirien/minectl/tree/main/config) folder for all supported cloud providers and Minecraft editions.
## MinecraftProxy Config
If you want to start a server with a Minecraft Proxy, you need to define a MinecraftProxy manifest:
```yaml
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftProxy
metadata:
name: minecraft-proxy
spec:
server:
cloud: civo|scaleway|do|hetzner|akamai|ovh|gce|vultr|azure|oci|aws|vexxhost|fuga|multipass|exoscale
region:
size:
ssh:
port: 22 # or your custom port
publickeyfile: ".pub"
fail2ban:
bantime: ""
maxretry: ""
port:
spot: true|false
arm: true|false
proxy:
java:
openjdk:
xmx:
xms:
options:
- "-XX:+UseG1GC"
- "-XX:+ParallelRefProcEnabled"
- "-XX:MaxGCPauseMillis=200"
rcon:
password:
port:
enabled: true|false
broadcast: true|false
type: "bungeecord|waterfall|velocity"
version:
```
## Configuration Options
### Spot Instances
When you want to run a Minecraft server on a spot instance, use:
```yaml
spec:
server:
spot: true
```
This is currently supported by AWS, Azure, and GCP.
### EULA
You need to explicitly set the EULA property in the MinecraftServer manifest to indicate your agreement with the [Minecraft End User License](https://minecraft.net/terms):
```yaml
spec:
minecraft:
eula: true
```
### SSH Configuration
```yaml
spec:
server:
ssh:
port: 22 # Custom SSH port (default: 22)
publickeyfile: "~/.ssh/id_rsa.pub" # Path to SSH public key
fail2ban:
bantime: "600" # Ban time in seconds
maxretry: "5" # Max failed attempts before ban
```
You can also inline the public key content:
```yaml
spec:
server:
ssh:
publickey: "ssh-rsa AAAAB3 ... xxx"
```
### Java Options
Configure JVM settings for optimal performance:
```yaml
spec:
minecraft:
java:
openjdk: "17"
xmx: 4G
xms: 4G
options:
- "-XX:+UseG1GC"
- "-XX:+ParallelRefProcEnabled"
- "-XX:MaxGCPauseMillis=200"
- "-XX:+UnlockExperimentalVMOptions"
- "-XX:+DisableExplicitGC"
- "-XX:+AlwaysPreTouch"
- "-XX:G1NewSizePercent=30"
- "-XX:G1MaxNewSizePercent=40"
- "-XX:G1HeapRegionSize=8M"
- "-XX:G1ReservePercent=20"
- "-XX:G1HeapWastePercent=5"
- "-XX:G1MixedGCCountTarget=4"
- "-XX:InitiatingHeapOccupancyPercent=15"
- "-XX:G1MixedGCLiveThresholdPercent=90"
- "-XX:G1RSetUpdatingPauseTimePercent=5"
- "-XX:SurvivorRatio=32"
- "-XX:+PerfDisableSharedMem"
- "-XX:MaxTenuringThreshold=1"
```
### Server Properties
Configure Minecraft server properties directly in the manifest:
```yaml
spec:
minecraft:
properties: |
level-seed=minectlrocks
broadcast-rcon-to-ops=true
view-distance=10
max-players=20
difficulty=normal
gamemode=survival
pvp=true
spawn-monsters=true
spawn-animals=true
```
================================================
FILE: docs/dashboard/tutorial.json
================================================
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"id": 26,
"iteration": 1626068074665,
"links": [],
"panels": [
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "string"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 0
},
"id": 4,
"options": {
"colorMode": "value",
"graphMode": "area",
"justifyMode": "center",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"text": {},
"textMode": "auto"
},
"pluginVersion": "8.0.1",
"targets": [
{
"exemplar": false,
"expr": "minecraft_prometheus_exporter_blocks_mined_total{job=\"$server\", player=\"$player\"}",
"format": "time_series",
"hide": false,
"instant": true,
"interval": "",
"legendFormat": "",
"refId": "A"
}
],
"title": "blocks mined",
"transformations": [
{
"id": "labelsToFields",
"options": {
"valueLabel": "block"
}
}
],
"type": "stat"
},
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "string"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 0
},
"id": 6,
"options": {
"colorMode": "value",
"graphMode": "area",
"justifyMode": "center",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"text": {},
"textMode": "auto"
},
"pluginVersion": "8.0.1",
"targets": [
{
"exemplar": false,
"expr": "minecraft_prometheus_exporter_walk_one_cm_total{job=\"$server\", player=\"$player\"}",
"format": "time_series",
"hide": false,
"instant": true,
"interval": "",
"legendFormat": "",
"refId": "A"
}
],
"title": "Walk On CM",
"transformations": [
{
"id": "labelsToFields",
"options": {
"valueLabel": "block"
}
}
],
"type": "stat"
},
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {
"align": "center",
"displayMode": "color-text",
"filterable": false
},
"mappings": [],
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "string"
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 12,
"x": 0,
"y": 8
},
"id": 2,
"options": {
"showHeader": false
},
"pluginVersion": "8.0.1",
"targets": [
{
"exemplar": true,
"expr": "minecraft_prometheus_exporter_player_online_total{job=\"$server\"}",
"format": "table",
"instant": true,
"interval": "",
"legendFormat": "",
"refId": "A"
}
],
"title": "Online",
"transformations": [
{
"id": "filterFieldsByName",
"options": {
"include": {
"names": [
"player"
]
}
}
}
],
"type": "table"
},
{
"datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 8
},
"id": 5,
"options": {
"colorMode": "value",
"graphMode": "area",
"justifyMode": "center",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"text": {},
"textMode": "auto"
},
"pluginVersion": "8.0.1",
"targets": [
{
"exemplar": false,
"expr": "minecraft_prometheus_exporter_deaths_total{job=\"$server\", player=\"$player\"}",
"format": "time_series",
"hide": false,
"instant": false,
"interval": "",
"legendFormat": "",
"refId": "A"
}
],
"title": "💀",
"transformations": [
{
"id": "labelsToFields",
"options": {
"valueLabel": "block"
}
}
],
"type": "stat"
}
],
"refresh": "",
"schemaVersion": 30,
"style": "dark",
"tags": [],
"templating": {
"list": [
{
"allValue": null,
"current": {
"selected": true,
"text": "minecraft-server-do",
"value": "minecraft-server-do"
},
"datasource": null,
"definition": "label_values(job)",
"description": null,
"error": null,
"hide": 0,
"includeAll": false,
"label": null,
"multi": false,
"name": "server",
"options": [],
"query": {
"query": "label_values(job)",
"refId": "StandardVariableQuery"
},
"refresh": 1,
"regex": "minecraft-.*",
"skipUrlSync": false,
"sort": 0,
"type": "query"
},
{
"allValue": null,
"current": {
"selected": true,
"text": "ediri",
"value": "ediri"
},
"datasource": null,
"definition": "label_values(player)",
"description": null,
"error": null,
"hide": 0,
"includeAll": false,
"label": null,
"multi": false,
"name": "player",
"options": [],
"query": {
"query": "label_values(player)",
"refId": "StandardVariableQuery"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"type": "query"
}
]
},
"time": {
"from": "now-5m",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "minectl",
"uid": "JU4wDoink",
"version": 2
}
================================================
FILE: docs/editions.md
================================================
# Minecraft Editions
> `minectl` is not(!) providing any pre-compiled binaries of Minecraft or downloading a pre-compiled version.
>
> Every _non-vanilla_ version will be compiled during the build phase of your server.
## Server Editions
### Vanilla (Minecraft: Java Edition or Bedrock Edition)
The Vanilla software is the original, untouched, unmodified Minecraft server software created and distributed directly by Mojang.
### CraftBukkit
CraftBukkit is a lightly modified version of the Vanilla software allowing it to be able to run Bukkit plugins.
### Spigot
Spigot is the most popular Minecraft server software in the world. Spigot is a modified version of CraftBukkit with hundreds of improvements and optimizations that can only make CraftBukkit shrink in shame.
### PaperMC
Paper (formerly known as PaperSpigot, distributed via the Paperclip patch utility) is a high performance fork of Spigot.
### Purpur
Purpur is a drop-in replacement for Paper servers designed for configurability and new, fun, exciting gameplay features.
### Forge
Forge is well known for being able to use Forge Mods which are direct modifications to the Minecraft program code. In doing so, Forge Mods can change the gaming-feel drastically as a result of this.
### Fabric
Fabric is also a mod loader like Forge with some improvements. It's lightweight and faster and it may be the best mod loader in the future because it's doing very well.
### Nukkit
Nukkit is a nuclear-powered server software for Minecraft: Bedrock Edition, written in Java. It offers better performance and a plugin API for Bedrock servers.
### PowerNukkit
PowerNukkit is a modified version of Nukkit with additional features and bug fixes. It adds support for new blocks, items, and other features from recent Minecraft updates.
## Proxy Editions
Network proxy server is what you set up and use as the controller of a network of servers - this is the server that connects all of your playable servers together so people can log in through one server IP, and then teleport between the separate servers in-game rather than having to log out and into each different one.
A server network typically consists of the following servers:
1. **The proxy server** itself running the desired software (BungeeCord being the most widely used and supported). This is the server that you would be advertising the IP of, as all players should be logging in through the proxy server at all times.
2. **The hub (or main) server**. When users connect to the network proxy server's IP, it will re-route those users to this server.
3. **Additional servers** beyond the main server. Once you have at least one server running the proxy and one as the hub, any other servers will be considered extra servers that you can teleport to from the hub.
### BungeeCord
BungeeCord is a useful software written in-house by the team at SpigotMC. It acts as a proxy between the player's client and the connected Minecraft servers. End-users of BungeeCord see no difference between it and a normal Minecraft server.
### Waterfall
Waterfall is a fork of BungeeCord, a proxy used primarily to teleport players between multiple Minecraft servers.
Waterfall focuses on three main areas:
- Stability
- Features
- Scalability
### Velocity
A Minecraft server proxy with unparalleled server support, scalability, and flexibility. Velocity is licensed under the GPLv3 license.
- A codebase that is easy to dive into and consistently follows best practices for Java projects as much as reasonably possible
- High performance: handle thousands of players on one proxy
- A new, refreshing API built from the ground up to be flexible and powerful whilst avoiding design mistakes and suboptimal designs from other proxies
- First-class support for Paper, Sponge, and Forge (other implementations may work, but we make every endeavor to support these server implementations specifically)
---
Source: [SpigotMC Wiki](https://www.spigotmc.org/wiki/what-is-spigot-craftbukkit-bukkit-vanilla-forg/)
================================================
FILE: docs/features.md
================================================
# Features
## Monitoring
Monitoring is optional and disabled by default. Enable it by adding the following to your MinecraftServer manifest:
```yaml
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
monitoring:
enabled: true
server:
...
```
Every instance of `minectl` with monitoring enabled includes:
- [Prometheus](https://github.com/prometheus/prometheus)
- [Node exporter](https://github.com/prometheus/node_exporter)
The `edition:java` has an additional exporter included:
- [Minecraft exporter](https://github.com/dirien/minecraft-prometheus-exporter)
Access Prometheus via:
```
http://:9090/graph
```
For more details on monitoring, see [How to monitor your multi-cloud minectl server](multi-server-monitoring-civo.md).
## Volumes
With the `volumeSize` property, you can provision an extra volume during the creation phase of the server.
It is always recommended to use the provided volume of the server, but in some cases (large mod packs, community server, etc.) it makes sense to provision a bigger volume separately.
When a separate volume is defined, `minectl` automatically installs the Minecraft binaries on this volume.
```yaml
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: akamai
region: eu-central
size: g6-standard-4
volumeSize: 100
ssh:
port: 22
publickeyfile: ".pub"
fail2ban:
bantime: "600"
maxretry: "5"
port: 25565
minecraft:
...
```
## Security
### SSH Port
You can use the `port` property under the `ssh` object to define the SSH port of the server. The default SSH port is 22. Changing this helps avoid brute-force attacks on your server.
```yaml
spec:
server:
ssh:
port: 2222
```
### SSH Key
With the `publickeyfile` property, you can define the location of your SSH public key on your local machine:
```yaml
spec:
server:
ssh:
publickeyfile: "~/.ssh/id_rsa.pub"
```
Alternatively, use the `publickey` property to define the content of your SSH public key directly:
```yaml
spec:
server:
ssh:
publickey: "ssh-rsa AAAAB3 ... xxx"
```
If you need to update or upload a plugin to your server, provide the SSH private key in the command with the `--ssh-key` flag:
```bash
minectl update --filename server.yaml --id xxx --ssh-key ~/.ssh/id_rsa
```
### Fail2Ban
Fail2Ban is an intrusion prevention software framework that protects computer servers from brute-force attacks.
- `bantime` - The ban time in seconds
- `maxretry` - The maximum number of failed attempts before banning
If `maxretry` is reached, the IP is banned for the defined time (`bantime`).
```yaml
spec:
server:
ssh:
fail2ban:
bantime: "600"
maxretry: "5"
```
## Spot Instances
Run your Minecraft server on spot instances for cost savings:
```yaml
spec:
server:
spot: true
```
Currently supported by:
- AWS
- Azure
- GCP
> **Note:** Spot instances can be terminated by the cloud provider with short notice. Use for non-critical or easily recoverable servers.
## ARM Support
Run on ARM-based instances for cost efficiency:
```yaml
spec:
server:
arm: true
```
> **Attention:** Please lookup the correct service size when setting the `arm` attribute to `true`. Not all instance types are available on ARM.
================================================
FILE: docs/getting-started-civo-bedrock.md
================================================

# Getting Started on Civo with the Bedrock edition
Bedrock Edition (also known as the Bedrock editions, Bedrock versions, or just Bedrock) refers to the multi-platform
versions of Minecraft developed by Mojang Studios, Xbox Game Studios, and SkyBox Labs and based on the Bedrock codebase.
To setup a bedrock server, just follow [getting started with Civo](getting-started-civo.md) except of following changes:
###### Attention: The server.properties of the bedrock edition is different to the java edition
## Create MinecraftServer bedrock config
```bash
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: civo
region: LON1
size: g3.large
ssh: "xxx/ssh/minecraft.pub"
port: 19132
minecraft:
edition: bedrock
version: 1.17.10.04
eula: true
properties: |
server-name=Civo Minecraft
gamemode=survival
force-gamemode=false
difficulty=normal
allow-cheats=false
max-players=100
online-mode=true
white-list=false
server-portv6=19133
view-distance=32
tick-distance=4
player-idle-timeout=30
max-threads=8
level-name=Bedrock level
level-seed=
default-player-permission-level=member
texturepack-required=false
content-log-file-enabled=false
compression-threshold=1
server-authoritative-movement=server-auth
player-movement-score-threshold=20
player-movement-distance-threshold=0.3
player-movement-duration-threshold-in-ms=500
correct-player-movement=false
server-authoritative-block-breaking=false
```
## minectl 🗺
```bash
minectl create --filename config/server-civo.yaml
🛎 Using cloud provider Civo
🗺 Minecraft bedrock edition
🏗 Creating instance (minecraft-server)... ⣟
✅ Instance (minecraft-server) created
Minecraft Server IP: 74.220.17.6
Minecraft Server ID: c697ba04-8e22-44d0-b491-74622d637938
To delete the server type:
minectl delete -f config/bedrock/server-civo.yaml --id c697ba04-8e22-44d0-b491-74622d637938
```
## Minecraft Mobile Client
In this document, I use the iPhone Minecraft Client

Add your server


Join the server

Play the game

## minectl 🗺
Feed up with your bedrock server? Deleting is as easy as creating the server
```bash
minectl delete --filename config/server-civo.yaml --id a7ad735a-d1e9-4951-9f9b-83221efd945e
🛎 Using cloud provider Civo
🗺 Minecraft bedrock edition
🗑 Delete instance (c697ba04-8e22-44d0-b491-74622d637938)...
```
### Legal Disclaimer 👮
This project is not affiliated with Mojang Studios, XBox Game Studios, Double Eleven or the Minecraft brand.
"Minecraft" is a trademark of Mojang Synergies AB.
Apple, the Apple logo, Apple TV, Finder, Final Cut, Final Cut Pro, FireWire, GarageBand, Geneva, Inkwell, iPhone,
iPhoto, iPod, iTunes, iTunes Plus, Logic, Mac, Macintosh, Mac OS, MacBook, Pages, Pixlet, QuickTime, Spotlight, and
TrueType are trademarks of Apple Inc., registered in the U.S. and other countries.
Other trademarks referenced herein are property of their respective owners.
================================================
FILE: docs/getting-started-civo.md
================================================

# Getting Started - Civo edition
## API Key
Get your API Key via https://www.civo.com/account/security

Export the key as ENV variable:
```
export CIVO_TOKEN=xx
```
## Create SSH Keys
```
ssh-keygen -t rsa -f ./minecraft
```
## Create MinecraftServer config
```bash
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: civo
region: LON1
size: g3.large
ssh: "xxx/ssh/minecraft.pub"
port: 25565
minecraft:
java:
openjdk: 16
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: 1.17.1
eula: true
properties: |
level-seed=randomseed
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=Civo Minecraft
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
```
## minectl 🗺
```bash
minectl create --filename config/java/server-civo.yaml
🛎 Using cloud provider Civo
🗺 Minecraft java edition
🏗 Creating instance (minecraft-server)... ⣷
✅ Instance (minecraft-server) created
Minecraft Server IP: 74.220.17.7
Minecraft Server ID: 7b9ed37c-fb35-49de-a996-a5f8ae7b7fc1
To delete the server type:
minectl delete -f config/java/server-civo.yaml --id 7b9ed37c-fb35-49de-a996-a5f8ae7b7fc1
```

## Minecraft Client
### Download
Download a Minecraft Client (Java Edition) under https://www.minecraft.net/en-us/get-minecraft
Start your Minecraft Client

Add your server

Join the server

Play the game

## minectl 🗺
Feed up with your server? Deleting is as easy as creating the server
```bash
minectl delete --filename config/java/server-civo.yaml --id a7ad735a-d1e9-4951-9f9b-83221efd945e
🛎 Using cloud provider Civo
🗺 Minecraft java edition
🗑 Delete instance (7b9ed37c-fb35-49de-a996-a5f8ae7b7fc1)...
```
### Legal Disclaimer 👮
This project is not affiliated with Mojang Studios, XBox Game Studios, Double Eleven or the Minecraft brand.
"Minecraft" is a trademark of Mojang Synergies AB.
Other trademarks referenced herein are property of their respective owners.
================================================
FILE: docs/getting-started-exoscale.md
================================================

# Getting Started with Exoscale
## Access and Secret Key
Generate a new access and secret key (https://portal.exoscale.com/iam/api-keys)
*Note: for a better security (and to protect your budget!), we suggest you to create a RESTRICTED key to limit the rights of minectl.*

Get the generated API keys and keep this information in a safe place.

Open a terminal and Export the keys as ENV variables:
```
export EXOSCALE_API_KEY=EXO...
export EXOSCALE_API_SECRET=...
```
See https://community.exoscale.com/documentation/iam/quick-start/ for more details on Exoscale Credentials (Identity and Access Management, Exoscale IAM).
## Create SSH Keys
```
ssh-keygen -t rsa -f ./minecraft
```
## Create MinecraftServer config
Create a file named server-exoscale.yaml with the example below.
Have a look at https://minecraft.wiki/w/Server.properties to configure your server.
```bash
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: exoscale
region: ch-gva-2
size: medium
ssh:
port: 22
publickeyfile: "/xxx/path/to/your/private/key"
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 17
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: 1.18.1
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
# survival, creative, adventure, spectator
gamemode=creative
# allow users to travel to the Nether
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=\u00a7c\u00a7lExoscale \u25b2 \u00a7fMinecraft \u00a7r- Java Edition
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
#allow users to fly
allow-flight=true
max-world-size=29999984
```
## minectl 🗺
Once your configuration file is created, we will use it with minectl (see below).
In your Exoscale organizsation, Minectl will then:
- create a new instance called minecraft-server and deploy all necessary components
- add a security group (minecraft-server-sg) to allow the network traffic to your server
- import your public SSH key (minecraft-server-ssh).
```bash
minectl create --filename config/server-exoscale.yaml
🛎 Using cloud provider Exoscale
🗺 Minecraft java edition
🏗 Creating server (minecraft-server)... ⢿
✅ Server (minecraft-server) created
🎬 Starting server...
✅ Server successfully started.
ID | NAME | REGION | TAGS | IP
---------------------------------------+------------------+----------+------+-----------------
4100ce1c-e3b0-4a63-b42d-ee76c75178e4 | minecraft-server | ch-gva-2 | | 194.182.163.187
🪓 To delete the server type:
minectl delete -f ./exoscale-server.yaml --id 4100ce1c-e3b0-4a63-b42d-ee76c75178e4
🆙 To update the server type:
minectl update -f ./exoscale-server.yaml --id 4100ce1c-e3b0-4a63-b42d-ee76c75178e4
🔌 Connected to RCON type:
minectl rcon -f ./exoscale-server.yaml --id 4100ce1c-e3b0-4a63-b42d-ee76c75178e4
🚧 Beta features:
⤴️ To upload a plugin type:
minectl plugins -f ./exoscale-server.yaml --id 4100ce1c-e3b0-4a63-b42d-ee76c75178e4 --plugin /x.jar --destination /minecraft/plugins
```

## Minecraft Client
### Download
Download a Minecraft Client (Java Edition) under https://www.minecraft.net/en-us/get-minecraft
### Start your Minecraft Client

### Add your server

### Join the server

### Play the game

## minectl 🗺
Feed up with your server? Deleting is as easy as creating the server
```bash
minectl delete -f ./exoscale-server.yaml --id 4100ce1c-e3b0-4a63-b42d-ee76c75178e4
🛎 Using cloud provider Exoscale
🗺 Minecraft java edition
🗑 Delete instance (4100ce1c-e3b0-4a63-b42d-ee76c75178e4)...
```
### Legal Disclaimer 👮
This project is not affiliated with Mojang Studios, XBox Game Studios, Double Eleven or the Minecraft brand.
- "Minecraft" is a trademark of Mojang Synergies AB.
- "Exoscale" is a trademark of Akenes SA, Switzerland.
Other trademarks referenced herein are property of their respective owners.
================================================
FILE: docs/getting-started-gce.md
================================================

# Getting Started - GCE edition
## How to create a Service Account in GCP via gcloud cli
```bash
# Get current projectID
export PROJECTID=$(gcloud config get-value core/project 2>/dev/null)
# Create a service account
gcloud iam service-accounts create minctl \
--description "minectl-sa service account" \
--display-name "minctl"
# Get service account email
export SERVICEACCOUNT=$(gcloud iam service-accounts list | grep minctl | awk '{print $2}')
# Assign appropriate roles to minectl service account
gcloud projects add-iam-policy-binding $PROJECTID \
--member serviceAccount:$SERVICEACCOUNT \
--role roles/compute.admin
gcloud projects add-iam-policy-binding $PROJECTID \
--member serviceAccount:$SERVICEACCOUNT \
--role roles/iam.serviceAccountUser
gcloud projects add-iam-policy-binding $PROJECTID \
--member serviceAccount:$SERVICEACCOUNT \
--role roles/compute.osAdminLogin
# Create minectl service account key file
gcloud iam service-accounts keys create key.json \
--iam-account $SERVICEACCOUNT
```
### Legal Disclaimer 👮
This project is not affiliated with Mojang Studios, XBox Game Studios, Double Eleven or the Minecraft brand.
"Minecraft" is a trademark of Mojang Synergies AB.
Other trademarks referenced herein are property of their respective owners.
================================================
FILE: docs/getting-started-scaleway.md
================================================

# Getting Started - Scaleway edition
## Access and Secret Key
Generate a new access and secret key (https://console.scaleway.com/project/credentials)

Get the generated API keys.

Export the keys as ENV variables:
```
export ACCESS_KEY=xxx
export SECRET_KEY=yyy
export ORGANISATION_ID=zzz
```
See https://www.scaleway.com/en/docs/generate-api-keys/ for even more details on Scaleway Credentials
## Create SSH Keys
```
ssh-keygen -t rsa -f ./minecraft
```
## Create MinecraftServer config
```bash
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: scaleway
region: fr-par-1
size: GP1-XS
ssh: "xxx/ssh/minecraft.pub"
port: 25565
minecraft:
java:
openjdk: 16
xmx: 2G
xms: 2G
rcon:
password: test
port: 25575
enabled: true
broadcast: true
edition: java
version: 1.17.1
eula: true
properties: |
level-seed=minectlrocks
view-distance=10
enable-jmx-monitoring=false
server-ip=
resource-pack-prompt=
gamemode=survival
allow-nether=true
enable-command-block=false
sync-chunk-writes=true
enable-query=false
op-permission-level=4
prevent-proxy-connections=false
resource-pack=
entity-broadcast-range-percentage=100
level-name=world
player-idle-timeout=0
motd=Scaleway Minecraft
query.port=25565
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
pvp=true
spawn-npcs=true
spawn-animals=true
snooper-enabled=true
difficulty=easy
function-permission-level=2
network-compression-threshold=256
text-filtering-config=
require-resource-pack=false
spawn-monsters=true
max-tick-time=60000
enforce-whitelist=false
use-native-transport=true
max-players=100
resource-pack-sha1=
spawn-protection=16
online-mode=true
enable-status=true
allow-flight=false
max-world-size=29999984
```
## minectl 🗺
```bash
minectl create --filename config/server-scaleway.yaml
🛎 Using cloud provider Scaleway
🗺 Minecraft java edition
🏗 Creating instance (minecraft-server)... ⢿
✅ Instance (minecraft-server) created
Minecraft Server IP: 51.15.132.219
Minecraft Server ID: 30a219f1-dff2-487f-a3cd-0b03d712de81
To delete the server type:
minectl delete -f config/java/server-scaleway.yaml --id 30a219f1-dff2-487f-a3cd-0b03d712de81
```

## Minecraft Client
### Download
Download a Minecraft Client (Java Edition) under https://www.minecraft.net/en-us/get-minecraft
Start your Minecraft Client

Add your server

Join the server

Play the game

## minectl 🗺
Feed up with your server? Deleting is as easy as creating the server
```bash
minectl delete -f config/java/server-scaleway.yaml --id 30a219f1-dff2-487f-a3cd-0b03d712de81
🛎 Using cloud provider Scaleway
🗺 Minecraft java edition
🗑 Delete instance (30a219f1-dff2-487f-a3cd-0b03d712de81)...
```
### Legal Disclaimer 👮
This project is not affiliated with Mojang Studios, XBox Game Studios, Double Eleven or the Minecraft brand.
"Minecraft" is a trademark of Mojang Synergies AB.
Other trademarks referenced herein are property of their respective owners.
================================================
FILE: docs/minectl.drawio
================================================
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
================================================
FILE: docs/multi-server-monitoring-civo.md
================================================




# How to monitor your multi-cloud minectl 🗺 server? - Civo edition
minectl 🗺 will be installed with following monitoring stack:
- Prometheus (https://github.com/prometheus/prometheus)
- Node exporter (https://github.com/prometheus/node_exporter)
- Minecraft exporter (https://github.com/dirien/minecraft-prometheus-exporter)
So you don't need to do anything. You can directly access your Prometheus instance via `http://:9090/graph` in the
browser of your choice.

Every target is already configured, and you are ready to go.

So how, we can use this setting to monitor multi-cloud minectl 🗺 server?
Enter the stage for `Civo`
# Civo, Kubernetes and the marketplace
Civo (https://www.civo.com), a UK-based startup, offers cloud native infrastructure services powered only by Kubernetes.
With launch times <
90s it is incredible fast and offers several state of the art ways of managing your clusters, using your favourite tools
like Terraform and Pulumi, or our simple to use CLI or API.
On top, Civo offers a curated marketplace of Kubernetes applications. With these we can quick and easy install them in
to our Civo Kubernetes clusters
# Create your Civo monitoring cluster
In these guide we will cover the CLI way to create a Civo monitoring cluster:
## CLI
Follow the instructions to install the [Civo CLI](https://github.com/civo/cli#set-up)
In order to use the command-line tool, you will need to authenticate yourself to the Civo API using a special key. You
can find an automatically-generated API key or regenerate a new key at https://www.civo.com/api.
So let us create a Civo Kubernetes Cluster and install the
[kube-prometheus-stack](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack) as
the base for our monitoring stack.
We will install the cert-manager directly via the marketplace.
````bash
civo k3s create minectl-monitoring --nodes=1 --size=g3.k3s.large \
--applications=cert-manager,Nginx \
--remove-applications=Traefik
````
`The cluster minectl-monitoring (10142bd2-d34d-4804-941f-1e98e4a577da) has been created`
Wait until the cluster is ready to use.
```bash
civo k3s ls
+--------------------------------------+--------------------+--------+-------+-------+----------+
| ID | Name | Region | Nodes | Pools | Status |
+--------------------------------------+--------------------+--------+-------+-------+----------+
| 10142bd2-d34d-4804-941f-1e98e4a577da | minectl-monitoring | LON1 | 0 | 0 | BUILDING |
+--------------------------------------+--------------------+--------+-------+-------+----------+
```
Get the kubeconfig or merge it your context. What ever you prefer.
```bash
civo k3s config minectl-monitoring --save -p civo.yaml
export KUBECONFIG=civo.yaml
kubectl get node
NAME STATUS ROLES AGE VERSION
k3s-minectl-monitoring-09b924fa-node-pool-2336 Ready 39s v1.20.2+k3s1
```
The good part is, that we already installed the nginx ingress controller and the cert-manger. So we can directly dive
into the installation of
the [kube-prometheus-stack](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack)
### Kubernetes
#### cert-manger
Prepare a DNS Alias (I use `grafana-minectl.ediri.online`) and point to the public IP of your ingress controller:

```bash
kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller-admission ClusterIP 10.43.141.34 443/TCP 30m
ingress-nginx-controller LoadBalancer 10.43.58.0 74.220.21.72 80:30780/TCP,443:31620/TCP 30m
```
Let us now install the ns, certificate, and the (cluster)-issuer for our Grafana UI. As namespace, we use `monitoring`,
that will also the namespace we deploy the monitoring stack too.
```yaml
cat < values.yaml
grafana:
persistence:
enabled: true
size: 50Gi
storageClassName: civo-volume
serviceMonitor:
enabled: true
interval: 1m
selfMonitor: false
ingress:
annotations:
kubernetes.io/ingress.class: nginx
enabled: true
tls:
- secretName: ediri-online-tls
hosts:
- grafana-minectl.ediri.online
hosts:
- grafana-minectl.ediri.online
alertmanagerSpec:
storage:
volumeClaimTemplate:
spec:
storageClassName: civo-volume
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 5Gi
prometheus:
ingress:
enabled: false
prometheusSpec:
replicas: 1
storageSpec:
volumeClaimTemplate:
spec:
storageClassName: civo-volume
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 50Gi
EOF
```
```bash
helm upgrade -i monitoring prometheus-community/kube-prometheus-stack -n monitoring -f values.yaml
```
If everything works fine, you should be greeted with the Grafana screen. With a valid SSL certificate.

Login with the defaults `admin:prom-operator`
To get the minecraft metrics to appear in the prometheus, we need to use the Kubernetes service of type `ExternalName`
with `Endpoint` and the `ServiceMonitor`.
```yaml
cat < Originally created in 2015, the Lucky Block is a mod for Minecraft which has since gained over 5 million users. The mod adds a new block to the game which produces random outcomes, as well as items such as the lucky sword, bow and potion. Additionally, the mod can be customized with hundreds of community add-ons.
See https://github.com/alexsocha/luckyblock for details.
## RAM consumption and Minecraft.
A rule of thumb is. Every 1GB of RAM enables you around ~10-15 Slots for players to join.
Also, we need an eye on the amount of plugins, we are going to use. Mods and Plugins can really can have a bad impact on
your server performance.
So a rough table could look like this:
|RAM|Player|
|---|---|
|1GB|15|
|2GB|30|
|3GB|45|
|5GB|75|
|6GB|90|
|7GB|100|
|8GB|120|
## Scaleway instances
[Scaleway](https://www.scaleway.com/en/) is the rising star in the European Cloud provider market.
What I like on Scaleway, apart may other things, is that they are `Green` from the start.
> the most environmentally efficient and transparent cloud worldwide
Scaleway has this amazing [DEV1-S](https://www.scaleway.com/en/pricing/#development-instances) in their offering.
> 2 vCPU, 2 GB of RAM, 1 IPv4 address, 20B of local storage
For whopping €0.01/hour (~ $0,012/hour) you get enough power, for a small server. Perfect for a little play with friends.
## Assembly
### Server
> You need a valid SSH keypair. Generate it with following command:
>
> `ssh-keygen -t rsa -f scaleway-ssh`
Let us build the parts, so we can deploy our Lucky Block server
The `minectl` ServerManifest for Scaleway DEV1-S and Forge looks like this:
```yaml
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: scaleway
region: fr-par-1
size: DEV1-S
ssh: "scaleway-ssh"
port: 25565
minecraft:
java:
openjdk: 8
xmx: 1G
xms: 1G
rcon:
password: stardust
port: 25575
enabled: true
broadcast: true
edition: forge
version: 1.16.5-36.2.0
eula: true
properties: |
motd=\u00A75Scalway \u00A7lSTARDUST \u00A7rMinecraft -- \u00A76Forge \u00A7redition with \u00A7eLucky Block
level-seed=minectlrocks
level-name=world
```
Save this to `scaleway.yaml`
Export the keys as ENV variables:
```
export ACCESS_KEY=xxx
export SECRET_KEY=yyy
export ORGANISATION_ID=zzz
```
Now we can launch our instance via `minectl`
```bash
minectl create -f stardust.yaml
```
Hold on, this can take a while. As `minectl` is compiling the Forge server from scratch.
Wait until you can see the server in your Minecraft Launcher:

Don't mind the version error. We come back later.
Add the Luck Block plugin. Go to the [Download](https://www.luckyblockmod.com/download?platform=forge) and download your
version of Lucky Block.
In above case, I am downloading the `1.16.5-1` version.
After this we can use `minectl` to upload the jar to the `/minecraft/mods` folder
```bash
minectl plugins -f scaleway.yaml --id d62a5331-a6e8-4a92-b1d2-c84800b822e0 --plugin luckyblock-1.16.5-1-forge.jar --destination /minecraft/mods
```
### Minecraft Client
Download the [Forge installer](https://files.minecraftforge.net/net/minecraftforge/forge/index_1.16.5.html), again we
use version `1.16.5 - 36.2.0`and run it:
```bash
java -jar forge-1.16.5-36.2.0-installer.jar
```
Select the `Install client` and point the Folder to location of your Minecraft client.

Copy the `luckyblock-1.16.5-1-forge.jar` you downloaded for the server to the `mods` folder in your client directory.
```bash
cp luckyblock-1.16.5-1-forge.jar /Users/dirien/Library/Application Support/minecraft/mods/luckyblock-1.16.5-1-forge.jar
```
Start your Minecraft client
You should have now following item selectable in the Launcher:

Select the `forge` item and press `Play`
Now the Server in the list is good to go.

To see some Lucky Block, I switched to creative mode and placed some blocks by hand. To do this I use a RCON client, to
give my user Admin rights.

🎊 That's it, have fun...
### Legal Disclaimer 👮
This project is not affiliated with Mojang Studios, XBox Game Studios, Double Eleven or the Minecraft brand.
"Minecraft" is a trademark of Mojang Synergies AB.
Other trademarks referenced herein are property of their respective owners.
================================================
FILE: docs/skyblock-papermc-hetzner.md
================================================

# Running a PaperMC SkyBlock server - Hetzner edition

SkyBlock is the most fun and addictive game mode, next to BedWars.
So why not use `minectl` to create a SkyBlock server.
For this tutorial, we are going to use PaperMC as server and the [BentoBox](https://github.com/BentoBoxWorld/BentoBox)
plugin.
## PaperMC
Paper (formerly known as PaperSpigot, distributed via the Paperclip patch utility) is a high performance fork* of
Spigot.
## BentoBox
BentoBox is a powerful Bukkit library plugin that provides core features for island-style games like SkyBlock,
AcidIsland, SkyGrid and others.
## Hetzner
From their website:
> As a leading webhosting provider and experienced datacenter operator in Germany, Hetzner Online offers professional hosting solutions for a fair price.
For this installation we going to choose their `CX21` plan which offers is 2vCPU, 4GB RAM and 40GB of disk.
That's all for `0,010€/h` or `5,83€/mo` which is quite a nice price.
## Assembly
### Server
> You need a valid SSH keypair. Generate it with following command:
>
> `ssh-keygen -t rsa -f hetzner-ssh`
Let us build the parts, so we can deploy our BentoBox SkyBlocks server
The `minectl` ServerManifest for Hetzner CX21 and PaperMC looks like this:
```yaml
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: minecraft-server
spec:
server:
cloud: hetzner
region: nbg1
size: cx21
ssh: "hetzner-ssh"
port: 25565
minecraft:
java:
openjdk: 16
xmx: 1G
xms: 1G
rcon:
password: hetzner
port: 25575
enabled: true
broadcast: true
edition: papermc
version: 1.17.1-138
eula: true
properties: |
motd=\u00A7cHetzner \u00A7rMinecraft -- \u00A76PaperMC \u00A7redition with \u00A7eBSkyBlock
level-seed=minectlrocks
level-name=world
```
Save this to `hetzner.yaml`
Export the API token as ENV variables:
```
export HCLOUD_TOKEN=yyyy
```
Now we can launch our instance via `minectl`
```bash
minectl create -f hetzner.yaml
```
Wait until you can see the server in your Minecraft Launcher:

Now we can download the two plugins we need:
- BentoBox -> https://github.com/BentoBoxWorld/BentoBox/releases/tag/1.17.2
- BSkyBlock -> https://github.com/BentoBoxWorld/BSkyBlock/releases/tag/1.15.1
And upload them to our PaperMC server:
```bash
minectl plugins -f hetzner.yaml --id 13621910 --plugin plugins/BentoBox-1.17.2.jar --destination /minecraft/plugins
```
Wait that the server restarted and it's available in the launcher again, before uploading the second plugin.
According to the installation documents of BSkyBlock, it needs to be installed in the `addons` folder of the BentoBox.
So the upload command will look like this:
```bash
minectl plugins -f hetzner.yaml --id 13621910 --plugin plugins/BSkyBlock-1.15.1.jar --destination /minecraft/plugins/BentoBox/addons/
```
Wait again, for the server to be ready and join the server.
To enable BSkyBlock just type /skyblock in the ingame chat and choose an island

Done 🎊

### Legal Disclaimer 👮
This project is not affiliated with Mojang Studios, XBox Game Studios, Double Eleven or the Minecraft brand.
"Minecraft" is a trademark of Mojang Synergies AB.
Other trademarks referenced herein are property of their respective owners.
================================================
FILE: go.mod
================================================
module github.com/dirien/minectl
go 1.24.9
require (
github.com/Tnze/go-mc v1.20.2
github.com/blang/semver/v4 v4.0.0
github.com/c-bata/go-prompt v0.2.6
github.com/charmbracelet/bubbles v1.0.0
github.com/charmbracelet/bubbletea v1.3.10
github.com/charmbracelet/huh v1.0.0
github.com/charmbracelet/lipgloss v1.1.0
github.com/dirien/minectl-sdk v0.21.0
github.com/mitchellh/go-homedir v1.1.0
github.com/morikuni/aec v1.1.0
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.10.2
github.com/tcnksm/go-latest v0.0.0-20170313132115-e3007ae9052e
github.com/xeipuuv/gojsonschema v1.2.0
go.uber.org/zap v1.27.1
sigs.k8s.io/yaml v1.6.0
)
// replace github.com/dirien/minectl-sdk => ../minectl-sdk/
require (
cloud.google.com/go/auth v0.17.0 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
cloud.google.com/go/compute/metadata v0.9.0 // indirect
dario.cat/mergo v1.0.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v7 v7.2.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v8 v8.0.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources/v3 v3.0.1 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.3.0 // indirect
github.com/Masterminds/sprig/v3 v3.3.0 // indirect
github.com/atotto/clipboard v0.1.4 // indirect
github.com/aws/aws-sdk-go-v2 v1.41.0 // indirect
github.com/aws/aws-sdk-go-v2/config v1.32.6 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.19.6 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.16 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.16 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect
github.com/aws/aws-sdk-go-v2/service/ec2 v1.279.0 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.16 // indirect
github.com/aws/aws-sdk-go-v2/service/signin v1.0.4 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.30.8 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.41.5 // indirect
github.com/aws/smithy-go v1.24.0 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/catppuccin/go v0.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/charmbracelet/colorprofile v0.4.1 // indirect
github.com/charmbracelet/x/ansi v0.11.6 // indirect
github.com/charmbracelet/x/cellbuf v0.0.15 // indirect
github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 // indirect
github.com/charmbracelet/x/term v0.2.2 // indirect
github.com/civo/civogo v0.6.5 // indirect
github.com/clipperhouse/displaywidth v0.9.0 // indirect
github.com/clipperhouse/stringish v0.1.1 // indirect
github.com/clipperhouse/uax29/v2 v2.5.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deepmap/oapi-codegen v1.9.1 // indirect
github.com/digitalocean/godo v1.171.0 // indirect
github.com/dirien/ovh-go-sdk v0.2.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
github.com/exoscale/egoscale v0.101.1 // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-resty/resty/v2 v2.17.1 // indirect
github.com/gofrs/flock v0.10.0 // indirect
github.com/gofrs/uuid v4.4.0+incompatible // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
github.com/google/go-github v17.0.0+incompatible // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/google/s2a-go v0.1.9 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.7 // indirect
github.com/googleapis/gax-go/v2 v2.15.0 // indirect
github.com/gophercloud/gophercloud/v2 v2.9.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.8 // indirect
github.com/hashicorp/go-version v1.3.0 // indirect
github.com/hetznercloud/hcloud-go/v2 v2.33.0 // indirect
github.com/huandu/xstrings v1.5.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kr/fs v0.1.0 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/linode/linodego v1.63.0 // indirect
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-localereader v0.0.1 // indirect
github.com/mattn/go-runewidth v0.0.19 // indirect
github.com/mattn/go-tty v0.0.3 // indirect
github.com/melbahja/goph v1.4.0 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/termenv v0.16.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/oracle/oci-go-sdk/v65 v65.105.2 // indirect
github.com/ovh/go-ovh v1.3.0 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pkg/sftp v1.13.5 // indirect
github.com/pkg/term v1.2.0-beta.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.23.2 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.66.1 // indirect
github.com/prometheus/procfs v0.16.1 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.36 // indirect
github.com/sethvargo/go-password v0.3.1 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
github.com/sony/gobreaker v0.5.0 // indirect
github.com/spf13/cast v1.7.0 // indirect
github.com/spf13/pflag v1.0.9 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/stretchr/testify v1.11.1 // indirect
github.com/vultr/govultr/v3 v3.26.1 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
go.opentelemetry.io/otel v1.39.0 // indirect
go.opentelemetry.io/otel/metric v1.39.0 // indirect
go.opentelemetry.io/otel/trace v1.39.0 // indirect
go.uber.org/multierr v1.10.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
golang.org/x/crypto v0.46.0 // indirect
golang.org/x/net v0.48.0 // indirect
golang.org/x/oauth2 v0.34.0 // indirect
golang.org/x/sys v0.39.0 // indirect
golang.org/x/text v0.32.0 // indirect
golang.org/x/time v0.14.0 // indirect
google.golang.org/api v0.258.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b // indirect
google.golang.org/grpc v1.79.3 // indirect
google.golang.org/protobuf v1.36.11 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.66.6 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.27.1 // indirect
k8s.io/apimachinery v0.27.1 // indirect
k8s.io/klog/v2 v2.90.1 // indirect
k8s.io/utils v0.0.0-20230209194617-a36077c30491 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
)
================================================
FILE: go.sum
================================================
cloud.google.com/go/auth v0.17.0 h1:74yCm7hCj2rUyyAocqnFzsAYXgJhrG26XCFimrc/Kz4=
cloud.google.com/go/auth v0.17.0/go.mod h1:6wv/t5/6rOPAX4fJiRjKkJCvswLwdet7G8+UGXt7nCQ=
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0 h1:JXg2dwJUmPB9JmtVmdEB16APJ7jurfbY5jnfXpJoRMc=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0/go.mod h1:YD5h/ldMsG0XiIw7PdyNhLxaM317eFh5yNLccNfGdyw=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 h1:Hk5QBxZQC1jb2Fwj6mpzme37xbCDdNTxU7O9eb5+LB4=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1/go.mod h1:IYus9qsFobWIc2YVwe/WPjcnyCkPKtnHAqUYeebc8z0=
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY=
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2/go.mod h1:XtLgD3ZD34DAaVIIAyG3objl5DynM3CQ/vMcbBNJZGI=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v7 v7.2.0 h1:XQ+/r6WORQ1Gmz0z0XTJixAbuOxSQvPpNlcPgziXPis=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v7 v7.2.0/go.mod h1:3WoHXiNq+/VSiljks+B3s0y3qwxyASJpSozY0zlDmgA=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.1 h1:1kpY4qe+BGAH2ykv4baVSqyx+AY5VjXeJ15SldlU6hs=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.1/go.mod h1:nT6cWpWdUt+g81yuKmjeYPUtI73Ak3yQIT4PVVsCEEQ=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v8 v8.0.0 h1:7QO7GhGat25QEYL4h607O9zNNTUlAv8PbSesW6Ol5Gg=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v8 v8.0.0/go.mod h1:mCqeYzwyjn/pw0JVqHJMIzfUQJrlcV0YjTg5b0NK+F0=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armdeployments v0.2.0 h1:bYq3jfB2x36hslKMHyge3+esWzROtJNk/4dCjsKlrl4=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armdeployments v0.2.0/go.mod h1:fewgRjNVE84QVVh798sIMFb7gPXPp7NmnekGnboSnXk=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 h1:Dd+RhdJn0OTtVGaeDLZpcumkIVCtA/3/Fo42+eoYvVM=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0/go.mod h1:5kakwfW5CjC9KK+Q4wjXAg+ShuIm2mBMua0ZFj2C8PE=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources/v3 v3.0.1 h1:guyQA4b8XB2sbJZXzUnOF9mn0WDBv/ZT7me9wTipKtE=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources/v3 v3.0.1/go.mod h1:8h8yhzh9o+0HeSIhUxYny+rEQajScrfIpNktvgYG3Q8=
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM=
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE=
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 h1:XRzhVemXdgvJqCH0sFfrBUTnUJSBrBf7++ypk+twtRs=
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk=
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
github.com/Tnze/go-mc v1.20.2 h1:arHCE/WxLCxY73C/4ZNLdOymRYtdwoXE05ohB7HVN6Q=
github.com/Tnze/go-mc v1.20.2/go.mod h1:geoRj2HsXSkB3FJBuhr7wCzXegRlzWsVXd7h7jiJ6aQ=
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/aws/aws-sdk-go-v2 v1.41.0 h1:tNvqh1s+v0vFYdA1xq0aOJH+Y5cRyZ5upu6roPgPKd4=
github.com/aws/aws-sdk-go-v2 v1.41.0/go.mod h1:MayyLB8y+buD9hZqkCW3kX1AKq07Y5pXxtgB+rRFhz0=
github.com/aws/aws-sdk-go-v2/config v1.32.6 h1:hFLBGUKjmLAekvi1evLi5hVvFQtSo3GYwi+Bx4lpJf8=
github.com/aws/aws-sdk-go-v2/config v1.32.6/go.mod h1:lcUL/gcd8WyjCrMnxez5OXkO3/rwcNmvfno62tnXNcI=
github.com/aws/aws-sdk-go-v2/credentials v1.19.6 h1:F9vWao2TwjV2MyiyVS+duza0NIRtAslgLUM0vTA1ZaE=
github.com/aws/aws-sdk-go-v2/credentials v1.19.6/go.mod h1:SgHzKjEVsdQr6Opor0ihgWtkWdfRAIwxYzSJ8O85VHY=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16 h1:80+uETIWS1BqjnN9uJ0dBUaETh+P1XwFy5vwHwK5r9k=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16/go.mod h1:wOOsYuxYuB/7FlnVtzeBYRcjSRtQpAW0hCP7tIULMwo=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.16 h1:rgGwPzb82iBYSvHMHXc8h9mRoOUBZIGFgKb9qniaZZc=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.16/go.mod h1:L/UxsGeKpGoIj6DxfhOWHWQ/kGKcd4I1VncE4++IyKA=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.16 h1:1jtGzuV7c82xnqOVfx2F0xmJcOw5374L7N6juGW6x6U=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.16/go.mod h1:M2E5OQf+XLe+SZGmmpaI2yy+J326aFf6/+54PoxSANc=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.279.0 h1:o7eJKe6VYAnqERPlLAvDW5VKXV6eTKv1oxTpMoDP378=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.279.0/go.mod h1:Wg68QRgy2gEGGdmTPU/UbVpdv8sM14bUZmF64KFwAsY=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 h1:0ryTNEdJbzUCEWkVXEXoqlXV72J5keC1GvILMOuD00E=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4/go.mod h1:HQ4qwNZh32C3CBeO6iJLQlgtMzqeG17ziAA/3KDJFow=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.16 h1:oHjJHeUy0ImIV0bsrX0X91GkV5nJAyv1l1CC9lnO0TI=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.16/go.mod h1:iRSNGgOYmiYwSCXxXaKb9HfOEj40+oTKn8pTxMlYkRM=
github.com/aws/aws-sdk-go-v2/service/signin v1.0.4 h1:HpI7aMmJ+mm1wkSHIA2t5EaFFv5EFYXePW30p1EIrbQ=
github.com/aws/aws-sdk-go-v2/service/signin v1.0.4/go.mod h1:C5RdGMYGlfM0gYq/tifqgn4EbyX99V15P2V3R+VHbQU=
github.com/aws/aws-sdk-go-v2/service/sso v1.30.8 h1:aM/Q24rIlS3bRAhTyFurowU8A0SMyGDtEOY/l/s/1Uw=
github.com/aws/aws-sdk-go-v2/service/sso v1.30.8/go.mod h1:+fWt2UHSb4kS7Pu8y+BMBvJF0EWx+4H0hzNwtDNRTrg=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12 h1:AHDr0DaHIAo8c9t1emrzAlVDFp+iMMKnPdYy6XO4MCE=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12/go.mod h1:GQ73XawFFiWxyWXMHWfhiomvP3tXtdNar/fi8z18sx0=
github.com/aws/aws-sdk-go-v2/service/sts v1.41.5 h1:SciGFVNZ4mHdm7gpD1dgZYnCuVdX1s+lFTg4+4DOy70=
github.com/aws/aws-sdk-go-v2/service/sts v1.41.5/go.mod h1:iW40X4QBmUxdP+fZNOpfmkdMZqsovezbAeO+Ubiv2pk=
github.com/aws/smithy-go v1.24.0 h1:LpilSUItNPFr1eY85RYgTIg5eIEPtvFbskaFcmmIUnk=
github.com/aws/smithy-go v1.24.0/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/aymanbagabas/go-udiff v0.3.1 h1:LV+qyBQ2pqe0u42ZsUEtPiCaUoqgA9gYRDs3vj1nolY=
github.com/aymanbagabas/go-udiff v0.3.1/go.mod h1:G0fsKmG+P6ylD0r6N/KgQD/nWzgfnl8ZBcNLgcbrw8E=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/c-bata/go-prompt v0.2.6 h1:POP+nrHE+DfLYx370bedwNhsqmpCUynWPxuHi0C5vZI=
github.com/c-bata/go-prompt v0.2.6/go.mod h1:/LMAke8wD2FsNu9EXNdHxNLbd9MedkPnCdfpU9wwHfY=
github.com/catppuccin/go v0.3.0 h1:d+0/YicIq+hSTo5oPuRi5kOpqkVA5tAsU6dNhvRu+aY=
github.com/catppuccin/go v0.3.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/charmbracelet/bubbles v1.0.0 h1:12J8/ak/uCZEMQ6KU7pcfwceyjLlWsDLAxB5fXonfvc=
github.com/charmbracelet/bubbles v1.0.0/go.mod h1:9d/Zd5GdnauMI5ivUIVisuEm3ave1XwXtD1ckyV6r3E=
github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw=
github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4=
github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk=
github.com/charmbracelet/colorprofile v0.4.1/go.mod h1:U1d9Dljmdf9DLegaJ0nGZNJvoXAhayhmidOdcBwAvKk=
github.com/charmbracelet/huh v1.0.0 h1:wOnedH8G4qzJbmhftTqrpppyqHakl/zbbNdXIWJyIxw=
github.com/charmbracelet/huh v1.0.0/go.mod h1:5YVc+SlZ1IhQALxRPpkGwwEKftN/+OlJlnJYlDRFqN4=
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8=
github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ=
github.com/charmbracelet/x/cellbuf v0.0.15 h1:ur3pZy0o6z/R7EylET877CBxaiE1Sp1GMxoFPAIztPI=
github.com/charmbracelet/x/cellbuf v0.0.15/go.mod h1:J1YVbR7MUuEGIFPCaaZ96KDl5NoS0DAWkskup+mOY+Q=
github.com/charmbracelet/x/conpty v0.1.0 h1:4zc8KaIcbiL4mghEON8D72agYtSeIgq8FSThSPQIb+U=
github.com/charmbracelet/x/conpty v0.1.0/go.mod h1:rMFsDJoDwVmiYM10aD4bH2XiRgwI7NYJtQgl5yskjEQ=
github.com/charmbracelet/x/errors v0.0.0-20240508181413-e8d8b6e2de86 h1:JSt3B+U9iqk37QUU2Rvb6DSBYRLtWqFqfxf8l5hOZUA=
github.com/charmbracelet/x/errors v0.0.0-20240508181413-e8d8b6e2de86/go.mod h1:2P0UgXMEa6TsToMSuFqKFQR+fZTO9CNGUNokkPatT/0=
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ=
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 h1:qko3AQ4gK1MTS/de7F5hPGx6/k1u0w4TeYmBFwzYVP4=
github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0/go.mod h1:pBhA0ybfXv6hDjQUZ7hk1lVxBiUbupdw5R31yPUViVQ=
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY=
github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo=
github.com/charmbracelet/x/xpty v0.1.2 h1:Pqmu4TEJ8KeA9uSkISKMU3f+C1F6OGBn8ABuGlqCbtI=
github.com/charmbracelet/x/xpty v0.1.2/go.mod h1:XK2Z0id5rtLWcpeNiMYBccNNBrP2IJnzHI0Lq13Xzq4=
github.com/civo/civogo v0.6.5 h1:nS5TWJB2BnW1X26wN/nWGxYMgj6VEyZxSt/1OlKrQZw=
github.com/civo/civogo v0.6.5/go.mod h1:akFVdRAQfJi4t8pGduUOiBwaW/NSC9i45m/dzhF09AY=
github.com/clipperhouse/displaywidth v0.9.0 h1:Qb4KOhYwRiN3viMv1v/3cTBlz3AcAZX3+y9OLhMtAtA=
github.com/clipperhouse/displaywidth v0.9.0/go.mod h1:aCAAqTlh4GIVkhQnJpbL0T/WfcrJXHcj8C0yjYcjOZA=
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
github.com/clipperhouse/uax29/v2 v2.5.0 h1:x7T0T4eTHDONxFJsL94uKNKPHrclyFI0lm7+w94cO8U=
github.com/clipperhouse/uax29/v2 v2.5.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE=
github.com/deepmap/oapi-codegen v1.9.1 h1:yHmEnA7jSTUMQgV+uN02WpZtwHnz2CBW3mZRIxr1vtI=
github.com/deepmap/oapi-codegen v1.9.1/go.mod h1:PLqNAhdedP8ttRpBBkzLKU3bp+Fpy+tTgeAMlztR2cw=
github.com/digitalocean/godo v1.171.0 h1:QwpkwWKr3v7yxc8D4NQG973NoR9APCEWjYnLOQeXVpQ=
github.com/digitalocean/godo v1.171.0/go.mod h1:xQsWpVCCbkDrWisHA72hPzPlnC+4W5w/McZY5ij9uvU=
github.com/dirien/minectl-sdk v0.21.0 h1:YrIC19XO8/yVXO0woxtKslVpsJInG1HmgSw8MNeR+Es=
github.com/dirien/minectl-sdk v0.21.0/go.mod h1:tCQ/tFEoji6qX/mXDZeHDIIHh52WiSK4Seb8tR5a7qs=
github.com/dirien/ovh-go-sdk v0.2.0 h1:hIL39yxXnUNEUw1gn3g2cA9QKj2cHdbbowAyq8tHug4=
github.com/dirien/ovh-go-sdk v0.2.0/go.mod h1:kz6dmFoAym8NbdVTdGRzQuTGfRNoMrSuevxvxxBPVjA=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
github.com/exoscale/egoscale v0.101.1 h1:OqzwSpdMqbvycgAvxAkWrdY0pSGvpUDkyhNy3wAZEh0=
github.com/exoscale/egoscale v0.101.1/go.mod h1:szh4hWSVh+ylgfti4AFR4mkRaCfUyUXSKS3PihlcOco=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/getkin/kin-openapi v0.87.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
github.com/go-resty/resty/v2 v2.17.1 h1:x3aMpHK1YM9e4va/TMDRlusDDoZiQ+ViDu/WpA6xTM4=
github.com/go-resty/resty/v2 v2.17.1/go.mod h1:kCKZ3wWmwJaNc7S29BRtUhJwy7iqmn+2mLtQrOyQlVA=
github.com/goccy/go-json v0.7.8/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/gofrs/flock v0.10.0 h1:SHMXenfaB03KbroETaCMtbBg3Yn29v4w1r+tgy4ff4k=
github.com/gofrs/flock v0.10.0/go.mod h1:FirDy1Ing0mI2+kB6wk+vyyAH+e6xiE+EYA0jnzV9jc=
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.3.7 h1:zrn2Ee/nWmHulBx5sAVrGgAa0f2/R35S4DJwfFaUPFQ=
github.com/googleapis/enterprise-certificate-proxy v0.3.7/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
github.com/googleapis/gax-go/v2 v2.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo=
github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc=
github.com/gophercloud/gophercloud/v2 v2.9.0 h1:Y9OMrwKF9EDERcHFSOTpf/6XGoAI0yOxmsLmQki4LPM=
github.com/gophercloud/gophercloud/v2 v2.9.0/go.mod h1:Ki/ILhYZr/5EPebrPL9Ej+tUg4lqx71/YH2JWVeU+Qk=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48=
github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw=
github.com/hashicorp/go-version v1.3.0 h1:McDWVJIU/y+u1BRV06dPaLfLCaT7fUTJLp5r04x7iNw=
github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hetznercloud/hcloud-go/v2 v2.33.0 h1:g9hwuo60IXbupXJCYMlO4xDXgxxMPuFk31iOpLXDCV4=
github.com/hetznercloud/hcloud-go/v2 v2.33.0/go.mod h1:GzYEl7slIGKc6Ttt08hjiJvGj8/PbWzcQf6IUi02dIs=
github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI=
github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jarcoal/httpmock v1.4.1 h1:0Ju+VCFuARfFlhVXFc2HxlcQkfB+Xq12/EotHko+x2A=
github.com/jarcoal/httpmock v1.4.1/go.mod h1:ftW1xULwo+j0R0JJkJIIi7UKigZUXCLLanykgjwBXL0=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU=
github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/labstack/echo/v4 v4.6.3/go.mod h1:Hk5OiHj0kDqmFq7aHe7eDqI7CUhuCrfpupQtLGGLm7A=
github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
github.com/lestrrat-go/blackmagic v1.0.0/go.mod h1:TNgH//0vYSs8VXDCfkZLgIrVTTXQELZffUV0tz3MtdQ=
github.com/lestrrat-go/codegen v1.0.2/go.mod h1:JhJw6OQAuPEfVKUCLItpaVLumDGWQznd1VaXrBk9TdM=
github.com/lestrrat-go/httpcc v1.0.0/go.mod h1:tGS/u00Vh5N6FHNkExqGGNId8e0Big+++0Gf8MBnAvE=
github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc=
github.com/lestrrat-go/jwx v1.2.7/go.mod h1:bw24IXWbavc0R2RsOtpXL7RtMyP589yZ1+L7kd09ZGA=
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/linode/linodego v1.63.0 h1:MdjizfXNJDVJU6ggoJmMO5O9h4KGPGivNX0fzrAnstk=
github.com/linode/linodego v1.63.0/go.mod h1:GoiwLVuLdBQcAebxAVKVL3mMYUgJZR/puOUSla04xBE=
github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw=
github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
github.com/mattn/go-tty v0.0.3 h1:5OfyWorkyO7xP52Mq7tB36ajHDG5OHrmBGIS/DtakQI=
github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0=
github.com/melbahja/goph v1.4.0 h1:z0PgDbBFe66lRYl3v5dGb9aFgPy0kotuQ37QOwSQFqs=
github.com/melbahja/goph v1.4.0/go.mod h1:uG+VfK2Dlhk+O32zFrRlc3kYKTlV6+BtvPWd/kK7U68=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/morikuni/aec v1.1.0 h1:vBBl0pUnvi/Je71dsRrhMBtreIqNMYErSAbEeb8jrXQ=
github.com/morikuni/aec v1.1.0/go.mod h1:xDRgiq/iw5l+zkao76YTKzKttOp2cwPEne25HDkJnBw=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/onsi/gomega v1.27.4 h1:Z2AnStgsdSayCMDiCU42qIz+HLqEPcgiOCXjAU/w+8E=
github.com/onsi/gomega v1.27.4/go.mod h1:riYq/GJKh8hhoM01HN6Vmuy93AarCXCBGpvFDK3q3fQ=
github.com/oracle/oci-go-sdk/v65 v65.105.2 h1:AvZ59xNCGy/b4QT8j2HzIbE75K2nxYGeNirj7wX1XUw=
github.com/oracle/oci-go-sdk/v65 v65.105.2/go.mod h1:8ZzvzuEG/cFLFZhxg/Mg1w19KqyXBKO3c17QIc5PkGs=
github.com/ovh/go-ovh v1.3.0 h1:mvZaddk4E4kLcXhzb+cxBsMPYp2pHqiQpWYkInsuZPQ=
github.com/ovh/go-ovh v1.3.0/go.mod h1:AxitLZ5HBRPyUd+Zl60Ajaag+rNTdVXWIkzfrVuTXWA=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.13.5 h1:a3RLUqkyjYRtBTZJZ1VRrKbN3zhuPLlUc3sphVz81go=
github.com/pkg/sftp v1.13.5/go.mod h1:wHDZ0IZX6JcBYRK1TH9bcVq8G7TLpVHYIGJRFnmPfxg=
github.com/pkg/term v1.2.0-beta.2 h1:L3y/h2jkuBVFdWiJvNfYfKmzcCnILw7mJWm2JQuMppw=
github.com/pkg/term v1.2.0-beta.2/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.36 h1:ObX9hZmK+VmijreZO/8x9pQ8/P/ToHD/bdSb4Eg4tUo=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.36/go.mod h1:LEsDu4BubxK7/cWhtlQWfuxwL4rf/2UEpxXz1o1EMtM=
github.com/sethvargo/go-password v0.3.1 h1:WqrLTjo7X6AcVYfC6R7GtSyuUQR9hGyAj/f1PYQZCJU=
github.com/sethvargo/go-password v0.3.1/go.mod h1:rXofC1zT54N7R8K/h1WDUdkf9BOx5OptoxrMBcrXzvs=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg=
github.com/sony/gobreaker v0.5.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/tcnksm/go-latest v0.0.0-20170313132115-e3007ae9052e h1:IWllFTiDjjLIf2oeKxpIUmtiDV5sn71VgeQgg6vcE7k=
github.com/tcnksm/go-latest v0.0.0-20170313132115-e3007ae9052e/go.mod h1:d7u6HkTYKSv5m6MCKkOQlHwaShTMl3HjqSGW3XtVhXM=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/vultr/govultr/v3 v3.26.1 h1:G/M0rMQKwVSmL+gb0UgETbW5mcQi0Vf/o/ZSGdBCxJw=
github.com/vultr/govultr/v3 v3.26.1/go.mod h1:9WwnWGCKnwDlNjHjtt+j+nP+0QWq6hQXzaHgddqrLWY=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48=
go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8=
go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0=
go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs=
go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18=
go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE=
go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8=
go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew=
go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI=
go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
go.yaml.in/yaml/v4 v4.0.0-rc.3 h1:3h1fjsh1CTAPjW7q/EMe+C8shx5d8ctzZTrLcs/j8Go=
go.yaml.in/yaml/v4 v4.0.0-rc.3/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210913180222-943fd674d43e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200918232735-d647fc253266/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210114065538-d78b04bdf963/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/api v0.258.0 h1:IKo1j5FBlN74fe5isA2PVozN3Y5pwNKriEgAXPOkDAc=
google.golang.org/api v0.258.0/go.mod h1:qhOMTQEZ6lUps63ZNq9jhODswwjkjYYguA7fA3TBFww=
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuOnu87KpaYtjK5zBMLcULh7gxkCXu4=
google.golang.org/genproto v0.0.0-20250603155806-513f23925822/go.mod h1:HubltRL7rMh0LfnQPkMH4NPDFEWp0jw3vixw7jEM53s=
google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b h1:uA40e2M6fYRBf0+8uN5mLlqUtV192iiksiICIBkYJ1E=
google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:Xa7le7qx2vmqB/SzWUBa7KdMjpdpAHlh5QCSnjessQk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b h1:Mv8VFug0MP9e5vUxfBcE3vUkV6CImK3cMNMIDFjmzxU=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE=
google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/dnaeon/go-vcr.v4 v4.0.6 h1:PiJkrakkmzc5s7EfBnZOnyiLwi7o7A9fwPzN0X2uwe0=
gopkg.in/dnaeon/go-vcr.v4 v4.0.6/go.mod h1:sbq5oMEcM4PXngbcNbHhzfCP9OdZodLhrbRYoyg09HY=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI=
gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.27.1 h1:Z6zUGQ1Vd10tJ+gHcNNNgkV5emCyW+v2XTmn+CLjSd0=
k8s.io/api v0.27.1/go.mod h1:z5g/BpAiD+f6AArpqNjkY+cji8ueZDU/WV1jcj5Jk4E=
k8s.io/apimachinery v0.27.1 h1:EGuZiLI95UQQcClhanryclaQE6xjg1Bts6/L3cD7zyc=
k8s.io/apimachinery v0.27.1/go.mod h1:5ikh59fK3AJ287GUvpUsryoMFtH9zj/ARfWCo3AyXTM=
k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw=
k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/utils v0.0.0-20230209194617-a36077c30491 h1:r0BAOLElQnnFhE/ApUsg3iHdVYYPBjNSSOMowRZxxsY=
k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
================================================
FILE: internal/logging/logging.go
================================================
package logging
import (
"fmt"
"strings"
"github.com/charmbracelet/lipgloss"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
type MinectlLogging struct {
headless bool
}
func NewLogging(verbose, logEncoding string, headless bool) (*MinectlLogging, error) {
var level zapcore.Level
err := level.Set(verbose)
if err != nil {
return nil, err
}
cfg := zap.Config{
Encoding: logEncoding,
Level: zap.NewAtomicLevelAt(level),
EncoderConfig: zapcore.EncoderConfig{
MessageKey: "message",
LevelKey: "level",
EncodeLevel: zapcore.CapitalLevelEncoder,
TimeKey: "time",
EncodeTime: zapcore.ISO8601TimeEncoder,
CallerKey: "caller",
EncodeCaller: zapcore.ShortCallerEncoder,
},
}
if verbose != "" {
cfg.OutputPaths = []string{"stdout"}
cfg.ErrorOutputPaths = []string{"stderr"}
}
logger, _ := cfg.Build()
zap.ReplaceGlobals(logger)
return &MinectlLogging{
headless: headless,
}, nil
}
func (l *MinectlLogging) Error(msg error) {
if l.headless {
zap.S().Error(msg)
} else {
fmt.Println(msg)
}
}
func (l *MinectlLogging) RawMessage(msg string) {
if l.headless {
zap.S().Infow(strings.ReplaceAll(msg, "\n", ""))
} else {
fmt.Println(msg)
}
}
func (l *MinectlLogging) PrintMixedGreen(format, value string) {
if l.headless {
zap.S().Infow(strings.ReplaceAll(fmt.Sprintf(format, value), "\n", ""))
} else {
greenStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("10"))
fmt.Printf(format+"\n", greenStyle.Render(value))
}
}
// IsHeadless returns true if the logging instance is running in headless mode.
func (l *MinectlLogging) IsHeadless() bool {
return l.headless
}
================================================
FILE: internal/manifest/manifest.go
================================================
package manifest
import (
_ "embed"
"errors"
"fmt"
"os"
"regexp"
"strings"
"github.com/dirien/minectl-sdk/common"
"github.com/dirien/minectl-sdk/model"
"github.com/xeipuuv/gojsonschema"
"sigs.k8s.io/yaml"
)
type MinecraftServerManifest struct {
MinecraftServer *model.MinecraftResource
}
const (
MinecraftProxy = "MinecraftProxy"
MinecraftServer = "MinecraftServer"
)
//go:embed server.json
var server string
//go:embed proxy.json
var proxy string
func validate(manifest []byte) error {
var schemaLoader gojsonschema.JSONLoader
if strings.Contains(string(manifest), MinecraftProxy) {
schemaLoader = gojsonschema.NewStringLoader(proxy)
} else if strings.Contains(string(manifest), MinecraftServer) {
schemaLoader = gojsonschema.NewStringLoader(server)
}
yaml, err := yaml.YAMLToJSON(manifest)
if err != nil {
return err
}
documentLoader := gojsonschema.NewStringLoader(string(yaml))
result, err := gojsonschema.Validate(schemaLoader, documentLoader)
if err != nil {
return err
}
if !result.Valid() {
fmt.Printf("The document is not valid. see errors :\n")
for _, desc := range result.Errors() {
fmt.Printf("- %s\n", desc)
return errors.New("validation error")
}
}
return nil
}
func checkNamePattern(serverName string) error {
match, _ := regexp.MatchString(common.NameRegex, serverName)
if !match {
return errors.New("the name of your Minecraft server must consist of lower case alphanumeric characters or '-'")
}
return nil
}
func checkSSHPort(port int) error {
if port != 22 && (port < 1024 || port > 65535) {
return errors.New("the port must be between 1024 and 65535")
}
return nil
}
func NewMinecraftResource(manifestPath string) (*model.MinecraftResource, error) {
var server model.MinecraftResource
manifestFile, err := os.ReadFile(manifestPath)
if err != nil {
return nil, err
}
err = validate(manifestFile)
if err != nil {
return nil, err
}
err = yaml.Unmarshal(manifestFile, &server)
if err != nil {
return nil, err
}
err = checkNamePattern(server.GetName())
if err != nil {
return nil, err
}
err = checkSSHPort(server.GetSSHPort())
if err != nil {
return nil, err
}
return &server, nil
}
================================================
FILE: internal/manifest/proxy.json
================================================
{
"$schema": "http://json-schema.org/draft-06/schema#",
"$ref": "#/definitions/Welcome8",
"definitions": {
"Welcome8": {
"type": "object",
"additionalProperties": false,
"properties": {
"apiVersion": {
"type": "string"
},
"kind": {
"type": "string"
},
"metadata": {
"$ref": "#/definitions/Metadata"
},
"spec": {
"$ref": "#/definitions/Spec"
}
},
"required": [
"apiVersion",
"kind",
"metadata",
"spec"
],
"title": "Welcome8"
},
"Metadata": {
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string"
}
},
"required": [
"name"
],
"title": "Metadata"
},
"Spec": {
"type": "object",
"additionalProperties": false,
"properties": {
"server": {
"$ref": "#/definitions/Server"
},
"proxy": {
"$ref": "#/definitions/Proxy"
}
},
"required": [
"proxy",
"server"
],
"title": "Spec"
},
"Proxy": {
"type": "object",
"additionalProperties": false,
"properties": {
"java": {
"$ref": "#/definitions/Java"
},
"type": {
"type": "string"
},
"version": {
"type": "string"
}
},
"required": [
"java",
"type",
"version"
],
"title": "Proxy"
},
"Java": {
"type": "object",
"additionalProperties": false,
"properties": {
"openjdk": {
"type": "integer"
},
"xmx": {
"type": "string"
},
"xms": {
"type": "string"
},
"options": {
"type": "array",
"contains": {
"type": "string"
}
},
"rcon": {
"$ref": "#/definitions/Rcon"
}
},
"required": [
"openjdk",
"xms",
"xmx"
],
"title": "Java"
},
"Rcon": {
"type": "object",
"additionalProperties": false,
"properties": {
"password": {
"type": "string"
},
"enabled": {
"type": "boolean"
},
"port": {
"type": "integer"
},
"broadcast": {
"type": "boolean"
}
},
"required": [
"enabled"
],
"title": "Rcon"
},
"Server": {
"type": "object",
"additionalProperties": false,
"properties": {
"cloud": {
"type": "string"
},
"region": {
"type": "string"
},
"size": {
"type": "string"
},
"ssh": {
"type": "object",
"required": [
"port",
"fail2ban"
],
"oneOf": [
{
"required": [
"publickeyfile"
]
},
{
"required": [
"publickey"
]
}
],
"properties": {
"port": {
"type": "integer"
},
"publickeyfile": {
"type": "string"
},
"publickey": {
"type": "string"
},
"fail2ban": {
"type": "object",
"properties": {
"bantime": {
"type": "integer"
},
"maxretry": {
"type": "integer"
},
"ignoreip": {
"type": "string"
}
},
"additionalProperties": true
}
},
"additionalProperties": true
},
"port": {
"type": "integer"
}
},
"required": [
"cloud",
"port",
"region",
"size",
"ssh"
],
"title": "Server"
}
}
}
================================================
FILE: internal/manifest/server.json
================================================
{
"$schema": "http://json-schema.org/draft-06/schema#",
"$ref": "#/definitions/Welcome2",
"definitions": {
"Welcome2": {
"type": "object",
"additionalProperties": false,
"properties": {
"apiVersion": {
"type": "string"
},
"kind": {
"type": "string"
},
"metadata": {
"$ref": "#/definitions/Metadata"
},
"spec": {
"$ref": "#/definitions/Spec"
}
},
"required": [
"apiVersion",
"kind",
"metadata",
"spec"
],
"title": "Welcome2"
},
"Metadata": {
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string"
}
},
"required": [
"name"
],
"title": "Metadata"
},
"Monitoring": {
"type": "object",
"additionalProperties": false,
"properties": {
"enabled": {
"type": "boolean"
}
},
"required": [
"enabled"
],
"title": "Monitoring"
},
"Spec": {
"type": "object",
"additionalProperties": false,
"properties": {
"monitoring": {
"$ref": "#/definitions/Monitoring"
},
"server": {
"$ref": "#/definitions/Server"
},
"minecraft": {
"$ref": "#/definitions/Minecraft"
}
},
"required": [
"minecraft",
"server"
],
"title": "Spec"
},
"Minecraft": {
"type": "object",
"additionalProperties": false,
"properties": {
"java": {
"$ref": "#/definitions/Java"
},
"edition": {
"type": "string"
},
"eula": {
"type": "boolean"
},
"version": {
"type": "string"
},
"properties": {
"type": "string"
}
},
"required": [
"edition",
"version",
"eula"
],
"title": "Minecraft"
},
"Java": {
"type": "object",
"additionalProperties": false,
"properties": {
"openjdk": {
"type": "integer"
},
"xmx": {
"type": "string"
},
"xms": {
"type": "string"
},
"options": {
"type": "array",
"contains": {
"type": "string"
}
},
"rcon": {
"$ref": "#/definitions/Rcon"
}
},
"required": [
"xms",
"xmx",
"openjdk"
],
"title": "Java"
},
"Rcon": {
"type": "object",
"additionalProperties": false,
"properties": {
"password": {
"type": "string"
},
"enabled": {
"type": "boolean"
},
"port": {
"type": "integer"
},
"broadcast": {
"type": "boolean"
}
},
"required": [
"enabled"
],
"title": "Rcon"
},
"Server": {
"type": "object",
"additionalProperties": false,
"properties": {
"cloud": {
"type": "string"
},
"region": {
"type": "string"
},
"size": {
"type": "string"
},
"volumeSize": {
"type": "integer"
},
"arm": {
"type": "boolean"
},
"ssh": {
"type": "object",
"required": [
"port",
"fail2ban"
],
"oneOf": [
{
"required": [
"publickeyfile"
]
},
{
"required": [
"publickey"
]
}
],
"properties": {
"port": {
"type": "integer"
},
"publickeyfile": {
"type": "string"
},
"publickey": {
"type": "string"
},
"fail2ban": {
"type": "object",
"properties": {
"bantime": {
"type": "integer"
},
"maxretry": {
"type": "integer"
},
"ignoreip": {
"type": "string"
}
},
"additionalProperties": true
}
},
"additionalProperties": true
},
"port": {
"type": "integer"
},
"spot": {
"type": "boolean"
}
},
"required": [
"cloud"
],
"title": "Server"
}
}
}
================================================
FILE: internal/provisioner/provisioner.go
================================================
package provisioner
import (
"fmt"
"net"
"os"
"strconv"
"time"
"github.com/dirien/minectl-sdk/automation"
"github.com/dirien/minectl-sdk/cloud"
"github.com/dirien/minectl-sdk/cloud/akamai"
"github.com/dirien/minectl-sdk/cloud/aws"
"github.com/dirien/minectl-sdk/cloud/azure"
"github.com/dirien/minectl-sdk/cloud/civo"
"github.com/dirien/minectl-sdk/cloud/do"
"github.com/dirien/minectl-sdk/cloud/exoscale"
"github.com/dirien/minectl-sdk/cloud/fuga"
"github.com/dirien/minectl-sdk/cloud/gce"
"github.com/dirien/minectl-sdk/cloud/hetzner"
"github.com/dirien/minectl-sdk/cloud/multipass"
"github.com/dirien/minectl-sdk/cloud/oci"
"github.com/dirien/minectl-sdk/cloud/ovh"
"github.com/dirien/minectl-sdk/cloud/scaleway"
"github.com/dirien/minectl-sdk/cloud/vexxhost"
"github.com/dirien/minectl-sdk/cloud/vultr"
"github.com/dirien/minectl-sdk/common"
"github.com/dirien/minectl-sdk/model"
"github.com/dirien/minectl/internal/manifest"
"github.com/dirien/minectl/internal/rcon"
"github.com/dirien/minectl/internal/ui"
"github.com/pkg/errors"
)
const (
minecraftProxyTitle = "Minecraft %s Proxy"
minecraftServerTitle = "Minecraft %s edition"
minecraftSelectedCloudProviderTitle = "Using cloud provider %s"
minecraftListServersTitle = "Listing all servers"
minecraftServerDeletingTitle = "Deleting server (%s)..."
minecraftServerDeleteTitle = "Server (%s) deleted."
minecraftServerNotDeleteTitle = "Server (%s) not deleted."
minecraftServerCreatingTitle = "Creating server (%s)..."
minecraftServerCreateTitle = "Server (%s) created."
minecraftServerNotCreateTitle = "Server (%s) not created."
minecraftServerStartingTitle = "Starting server..."
minecraftServerStartTitle = "Server successfully started."
minecraftServerNotStartTitle = "Server failed to start."
minecraftServerUpdatingTitle = "Updating server (%s)..."
minecraftServerUpdateTitle = "Server (%s) updated."
minecraftServerNotUpdateTitle = "Server (%s) update failed."
startCheckCount = 50
)
type MinectlProvisionerOpts struct {
ManifestPath string
ID string
SSHPrivateKeyPath string
}
type MinectlProvisionerListOpts struct {
Provider string
Region string
}
type MinectlProvisioner struct {
auto automation.Automation
args automation.ServerArgs
ui *ui.UI
}
type Provisioner interface {
CreateServer(wait bool) (*automation.ResourceResults, error)
DeleteServer() error
UpdateServer() error
UploadPlugin(plugin, destination string) error
ListServer() ([]automation.ResourceResults, error)
GetServer() (*automation.ResourceResults, error)
DoRCON() error
}
func (p *MinectlProvisioner) GetServer() (*automation.ResourceResults, error) {
return p.auto.GetServer(p.args.ID, p.args)
}
func (p *MinectlProvisioner) DoRCON() error {
server, err := p.GetServer()
if err != nil {
return err
}
r := rcon.NewRCON(server.PublicIP, p.args.MinecraftResource.GetRCONPassword(), p.args.MinecraftResource.GetRCONPort())
r.RunPrompt()
return nil
}
func (p *MinectlProvisioner) UploadPlugin(plugin, destination string) error {
p.ui.Warn("Note: Plugins feature is still in beta.")
spinner := ui.NewSpinner(fmt.Sprintf("Uploading plugin to server (%s)...", common.Green(p.args.MinecraftResource.GetName())), p.ui)
spinner.FinalMessage = fmt.Sprintf("Plugin (%s) uploaded.", common.Green(p.args.MinecraftResource.GetName()))
spinner.ErrorMessage = fmt.Sprintf("Plugin (%s) not uploaded.", common.Green(p.args.MinecraftResource.GetName()))
spinner.Start()
err := p.auto.UploadPlugin(p.args.ID, p.args, plugin, destination)
spinner.Stop(err)
return err
}
func (p *MinectlProvisioner) UpdateServer() error {
spinner := ui.NewSpinner(fmt.Sprintf(minecraftServerUpdatingTitle, common.Green(p.args.MinecraftResource.GetName())), p.ui)
spinner.FinalMessage = fmt.Sprintf(minecraftServerUpdateTitle, common.Green(p.args.MinecraftResource.GetName()))
spinner.ErrorMessage = fmt.Sprintf(minecraftServerNotUpdateTitle, common.Green(p.args.MinecraftResource.GetName()))
spinner.Start()
err := p.auto.UpdateServer(p.args.ID, p.args)
spinner.Stop(err)
return err
}
// wait that server is ready... Currently, only for Java based Editions (TCP), as Bedrock is UDP
func (p *MinectlProvisioner) waitForMinecraftServerReady(server *automation.ResourceResults) error {
if p.args.MinecraftResource.GetEdition() != "bedrock" && p.args.MinecraftResource.GetEdition() != "nukkit" && p.args.MinecraftResource.GetEdition() != "powernukkit" {
spinner := ui.NewSpinner(minecraftServerStartingTitle, p.ui)
defer spinner.Stop(nil)
spinner.FinalMessage = minecraftServerStartTitle
spinner.ErrorMessage = minecraftServerNotStartTitle
spinner.Start()
check := net.JoinHostPort(server.PublicIP, strconv.Itoa(p.args.MinecraftResource.GetPort()))
checkCounter := 0
dialer := net.Dialer{Timeout: 15 * time.Second}
for checkCounter < startCheckCount {
timeout, err := dialer.Dial("tcp", check)
if err != nil {
time.Sleep(15 * time.Second)
checkCounter++
}
if timeout != nil {
err = timeout.Close()
if err != nil {
return errors.Errorf("timeout error: %s", err)
}
break
}
}
}
return nil
}
func (p *MinectlProvisioner) CreateServer(wait bool) (*automation.ResourceResults, error) {
spinner := ui.NewSpinner(fmt.Sprintf(minecraftServerCreatingTitle, common.Green(p.args.MinecraftResource.GetName())), p.ui)
spinner.FinalMessage = fmt.Sprintf(minecraftServerCreateTitle, common.Green(p.args.MinecraftResource.GetName()))
spinner.ErrorMessage = fmt.Sprintf(minecraftServerNotCreateTitle, common.Green(p.args.MinecraftResource.GetName()))
spinner.Start()
server, err := p.auto.CreateServer(p.args)
spinner.Stop(err)
if err != nil {
return nil, err
}
if wait {
err := p.waitForMinecraftServerReady(server)
if err != nil {
return nil, err
}
}
return server, err
}
func (p *MinectlProvisioner) ListServer() ([]automation.ResourceResults, error) {
return p.auto.ListServer()
}
func (p *MinectlProvisioner) DeleteServer() error {
spinner := ui.NewSpinner(fmt.Sprintf(minecraftServerDeletingTitle, common.Green(p.args.MinecraftResource.GetName())), p.ui)
spinner.FinalMessage = fmt.Sprintf(minecraftServerDeleteTitle, common.Green(p.args.MinecraftResource.GetName()))
spinner.ErrorMessage = fmt.Sprintf(minecraftServerNotDeleteTitle, common.Green(p.args.MinecraftResource.GetName()))
spinner.Start()
err := p.auto.DeleteServer(p.args.ID, p.args)
spinner.Stop(err)
return err
}
func ListProvisioner(options *MinectlProvisionerListOpts, u *ui.UI) (*MinectlProvisioner, error) {
u.Info(minecraftListServersTitle)
cloudProvider, err := getProvisioner(options.Provider, options.Region)
u.Info(fmt.Sprintf(minecraftSelectedCloudProviderTitle, cloud.GetCloudProviderFullName(options.Provider)))
if err != nil {
return nil, err
}
p := &MinectlProvisioner{
auto: cloudProvider,
ui: u,
}
return p, nil
}
func getProvisioner(provider, region string) (automation.Automation, error) { //nolint:gocyclo // large switch is inherent to provider selection
switch provider {
case model.PROVIDER_HETZNER:
cloudProvider, err := hetzner.NewHetzner(os.Getenv("HCLOUD_TOKEN"))
if err != nil {
return nil, err
}
return cloudProvider, nil
case model.PROVIDER_DIGITALOCEAN:
cloudProvider, err := do.NewDigitalOcean(os.Getenv("DIGITALOCEAN_TOKEN"))
if err != nil {
return nil, err
}
return cloudProvider, nil
case model.PROVIDER_CIVO:
cloudProvider, err := civo.NewCivo(os.Getenv("CIVO_TOKEN"), region)
if err != nil {
return nil, err
}
return cloudProvider, nil
case model.PROVIDER_SCALEWAY:
cloudProvider, err := scaleway.NewScaleway(os.Getenv("ACCESS_KEY"), os.Getenv("SECRET_KEY"), os.Getenv("ORGANISATION_ID"), region)
if err != nil {
return nil, err
}
return cloudProvider, nil
case model.PROVIDER_AKAMAI:
cloudProvider, err := akamai.NewAkamai(os.Getenv("LINODE_TOKEN"))
if err != nil {
return nil, err
}
return cloudProvider, nil
case model.PROVIDER_OVH:
cloudProvider, err := ovh.NewOVHcloud(os.Getenv("OVH_ENDPOINT"), os.Getenv("APPLICATION_KEY"), os.Getenv("APPLICATION_SECRET"), os.Getenv("CONSUMER_KEY"), os.Getenv("SERVICENAME"), region)
if err != nil {
return nil, err
}
return cloudProvider, nil
case model.PROVIDER_GCE:
cloudProvider, err := gce.NewGCE(region)
if err != nil {
return nil, err
}
return cloudProvider, nil
case model.PROVIDER_VULTR:
cloudProvider, err := vultr.NewVultr(os.Getenv("VULTR_API_KEY"))
if err != nil {
return nil, err
}
return cloudProvider, nil
case model.PROVIDER_AZURE:
cloudProvider, err := azure.NewAzure()
if err != nil {
return nil, err
}
return cloudProvider, nil
case model.PROVIDER_OCI:
cloudProvider, err := oci.NewOCI()
if err != nil {
return nil, err
}
return cloudProvider, nil
case model.PROVIDER_AWS:
cloudProvider, err := aws.NewAWS(region)
if err != nil {
return nil, err
}
return cloudProvider, nil
case model.PROVIDER_VEXXHOST:
cloudProvider, err := vexxhost.NewVEXXHOST()
if err != nil {
return nil, err
}
return cloudProvider, nil
case model.PROVIDER_FUGA:
cloudProvider, err := fuga.NewFuga()
if err != nil {
return nil, err
}
return cloudProvider, nil
case model.PROVIDER_EXOSCALE:
cloudProvider, err := exoscale.NewExoscale(os.Getenv("EXOSCALE_API_KEY"), os.Getenv("EXOSCALE_API_SECRET"))
if err != nil {
return nil, err
}
return cloudProvider, nil
case model.PROVIDER_MULTIPASS:
cloudProvider, err := multipass.NewMultipass()
if err != nil {
return nil, err
}
return cloudProvider, nil
default:
return nil, errors.Errorf("Could not find provider %s", provider)
}
}
func NewProvisioner(options *MinectlProvisionerOpts, u *ui.UI) (*MinectlProvisioner, error) {
var cloudProvider automation.Automation
minecraftResource, err := manifest.NewMinecraftResource(options.ManifestPath)
if err != nil {
return nil, err
}
args := automation.ServerArgs{
MinecraftResource: minecraftResource,
ID: options.ID,
SSHPrivateKeyPath: options.SSHPrivateKeyPath,
}
cloudProvider, err = getProvisioner(args.MinecraftResource.GetCloud(), args.MinecraftResource.GetRegion())
if err != nil {
return nil, err
}
u.Info(fmt.Sprintf(minecraftSelectedCloudProviderTitle, cloud.GetCloudProviderFullName(args.MinecraftResource.GetCloud())))
if args.MinecraftResource.IsProxyServer() {
u.Info(fmt.Sprintf(minecraftProxyTitle, args.MinecraftResource.GetEdition()))
} else {
u.Info(fmt.Sprintf(minecraftServerTitle, args.MinecraftResource.GetEdition()))
}
p := &MinectlProvisioner{
auto: cloudProvider,
args: args,
ui: u,
}
return p, nil
}
================================================
FILE: internal/rcon/rcon.go
================================================
package rcon
import (
"fmt"
mcnet "github.com/Tnze/go-mc/net"
prompt "github.com/c-bata/go-prompt"
)
type RCON struct {
server string
port int
password string
prompt *prompt.Prompt
}
type RCONer interface {
RunPrompt()
}
func (r *RCON) RunPrompt() {
fmt.Println("Connected to RCON (control-D to exit)\nType 'help' for list of commands")
r.prompt.Run()
}
func (r *RCON) executor(t string) {
conn, err := mcnet.DialRCON(fmt.Sprintf("%s:%d", r.server, r.port), r.password)
if err != nil {
fmt.Printf("Error dialing to RCON: %s\n", err.Error())
return
}
defer func(conn mcnet.RCONClientConn) {
err := conn.Close()
if err != nil {
fmt.Printf("Error closing RCON client: %s\n", err.Error())
}
}(conn)
err = conn.Cmd(t)
if err != nil {
fmt.Printf("Error executing command: %s\n", err.Error())
}
resp, err := conn.Resp()
if err != nil {
fmt.Printf("Error retrieving RCON response: %s\n", err.Error())
return
}
fmt.Println(resp)
}
func completer(_ prompt.Document) []prompt.Suggest {
return []prompt.Suggest{}
}
func NewRCON(server, passwort string, port int) *RCON {
r := &RCON{
server: server,
password: passwort,
port: port,
}
p := prompt.New(
r.executor,
completer,
prompt.OptionPrefix(">>> "),
prompt.OptionTitle("minectl RCON"),
)
r.prompt = p
return r
}
================================================
FILE: internal/ui/form.go
================================================
// Package ui provides terminal UI components for minectl using the Charm ecosystem.
package ui
import (
"errors"
"github.com/charmbracelet/huh"
"github.com/charmbracelet/lipgloss"
)
// FormTheme returns a consistent theme for Huh forms.
func FormTheme() *huh.Theme {
t := huh.ThemeBase()
t.Focused.Title = lipgloss.NewStyle().
Foreground(lipgloss.Color("229")).
Bold(true)
t.Focused.Description = lipgloss.NewStyle().
Foreground(lipgloss.Color("240"))
t.Focused.SelectSelector = lipgloss.NewStyle().
Foreground(lipgloss.Color("205"))
t.Focused.SelectedOption = lipgloss.NewStyle().
Foreground(lipgloss.Color("229"))
t.Focused.UnselectedOption = lipgloss.NewStyle().
Foreground(lipgloss.Color("250"))
return t
}
// RunForm runs a Huh form with consistent styling.
// In headless mode, it will use accessible mode for better CI/CD compatibility.
func RunForm(form *huh.Form, headless bool) error {
if headless {
form = form.WithAccessible(true)
}
return form.WithTheme(FormTheme()).Run()
}
// Confirm displays a yes/no confirmation prompt.
// Returns true if the user confirmed, false otherwise.
func Confirm(title string) (bool, error) {
confirmed := true
confirm := huh.NewConfirm().
Title(title).
Affirmative("Yes").
Negative("No").
Inline(true).
Value(&confirmed)
err := confirm.Run()
if err != nil {
if errors.Is(err, huh.ErrUserAborted) {
return false, nil
}
return false, err
}
return confirmed, nil
}
================================================
FILE: internal/ui/spinner.go
================================================
package ui
import (
"fmt"
"os"
"sync"
"github.com/charmbracelet/bubbles/spinner"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"go.uber.org/zap"
)
// Spinner provides an animated spinner for long-running operations.
// In headless mode, it falls back to simple log messages.
type Spinner struct {
Message string
FinalMessage string
ErrorMessage string
headless bool
program *tea.Program
mu sync.Mutex
started bool
done chan struct{}
}
// spinnerModel is the Bubble Tea model for the spinner.
type spinnerModel struct {
spinner spinner.Model
message string
quitting bool
}
func (m spinnerModel) Init() tea.Cmd {
return m.spinner.Tick
}
func (m spinnerModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
if msg.String() == "ctrl+c" {
m.quitting = true
return m, tea.Quit
}
case spinner.TickMsg:
var cmd tea.Cmd
m.spinner, cmd = m.spinner.Update(msg)
return m, cmd
case quitMsg:
m.quitting = true
return m, tea.Quit
}
return m, nil
}
func (m spinnerModel) View() string {
if m.quitting {
return ""
}
return fmt.Sprintf("%s %s", m.spinner.View(), m.message)
}
// quitMsg is sent to stop the spinner.
type quitMsg struct{}
// NewSpinner creates a new animated spinner.
func NewSpinner(message string, u *UI) *Spinner {
return &Spinner{
Message: message,
headless: u.IsHeadless(),
done: make(chan struct{}),
}
}
// Start begins the spinner animation.
func (s *Spinner) Start() {
s.mu.Lock()
defer s.mu.Unlock()
if s.headless {
zap.S().Infow(s.Message)
return
}
sp := spinner.New()
sp.Spinner = spinner.Dot
sp.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("205"))
model := spinnerModel{
spinner: sp,
message: s.Message,
}
s.program = tea.NewProgram(model, tea.WithOutput(os.Stderr))
s.started = true
go func() {
if _, err := s.program.Run(); err != nil {
zap.S().Debugw("spinner program error", "error", err)
}
close(s.done)
}()
}
// Stop stops the spinner and displays the appropriate final message.
func (s *Spinner) Stop(err error) {
s.mu.Lock()
var message string
if err != nil {
message = s.ErrorMessage
} else {
message = s.FinalMessage
}
if s.headless {
s.mu.Unlock()
if message != "" {
if err != nil {
zap.S().Errorw(message)
} else {
zap.S().Infow(message)
}
}
return
}
prog := s.program
started := s.started
s.mu.Unlock()
// Send quit and wait outside of the lock to avoid deadlock
if started && prog != nil {
prog.Send(quitMsg{})
<-s.done
}
if message != "" {
if err != nil {
fmt.Fprintln(os.Stderr, errorStyle.Render("✗ "+message))
} else {
fmt.Fprintln(os.Stderr, successStyle.Render("✓ "+message))
}
}
}
================================================
FILE: internal/ui/spinner_test.go
================================================
package ui
import (
"errors"
"testing"
"github.com/dirien/minectl/internal/logging"
)
func newTestUI(t *testing.T, headless bool) *UI {
t.Helper()
l, err := logging.NewLogging("info", "console", headless)
if err != nil {
t.Fatalf("failed to create logging: %v", err)
}
return NewUI(headless, l)
}
func TestNewSpinner(t *testing.T) {
tests := []struct {
name string
message string
headless bool
}{
{"headless spinner", "creating server...", true},
{"interactive spinner", "creating server...", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
u := newTestUI(t, tt.headless)
s := NewSpinner(tt.message, u)
if s.Message != tt.message {
t.Errorf("got Message %q, want %q", s.Message, tt.message)
}
if s.headless != tt.headless {
t.Errorf("got headless=%v, want %v", s.headless, tt.headless)
}
if s.started {
t.Error("expected started to be false for new spinner")
}
})
}
}
func TestSpinnerHeadlessStartStop(t *testing.T) {
tests := []struct {
name string
stopErr error
wantStarted bool
wantHeadless bool
}{
{"stop without error", nil, false, true},
{"stop with error", errors.New("server failed"), false, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
u := newTestUI(t, true)
s := NewSpinner("creating server...", u)
s.FinalMessage = "server created"
s.ErrorMessage = "server failed"
s.Start()
if !s.headless {
t.Error("expected headless mode")
}
// In headless mode, started remains false (no goroutine launched)
if s.started != tt.wantStarted {
t.Errorf("got started=%v, want %v", s.started, tt.wantStarted)
}
s.Stop(tt.stopErr)
})
}
}
func TestSpinnerStopWithoutStart(t *testing.T) {
tests := []struct {
name string
headless bool
}{
{"headless mode", true},
{"interactive mode", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
u := newTestUI(t, tt.headless)
s := NewSpinner("test", u)
s.FinalMessage = "done"
// Stop without Start should not panic
s.Stop(nil)
if s.started {
t.Error("expected started to be false")
}
})
}
}
================================================
FILE: internal/ui/table.go
================================================
package ui
import (
"fmt"
"io"
"strings"
"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/lipgloss/table"
)
// TableStyle defines the visual style for tables.
type TableStyle struct {
HeaderStyle lipgloss.Style
CellStyle lipgloss.Style
BorderStyle lipgloss.Style
}
// DefaultTableStyle returns the default styling for tables.
func DefaultTableStyle() TableStyle {
return TableStyle{
HeaderStyle: lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color("229")).
Background(lipgloss.Color("57")).
Padding(0, 1),
CellStyle: lipgloss.NewStyle().
Padding(0, 1),
BorderStyle: lipgloss.NewStyle().
Foreground(lipgloss.Color("240")),
}
}
// Table wraps lipgloss table with minectl styling.
type Table struct {
headers []string
rows [][]string
style TableStyle
headless bool
}
// NewTable creates a new styled table.
func NewTable(u *UI, headers ...string) *Table {
return &Table{
headers: headers,
rows: make([][]string, 0),
style: DefaultTableStyle(),
headless: u.IsHeadless(),
}
}
// Append adds a row to the table.
func (t *Table) Append(row []string) {
t.rows = append(t.rows, row)
}
// buildTable creates the styled lipgloss table.
func (t *Table) buildTable() *table.Table {
return table.New().
Border(lipgloss.RoundedBorder()).
BorderStyle(t.style.BorderStyle).
Headers(t.headers...).
Rows(t.rows...).
StyleFunc(func(row, _ int) lipgloss.Style {
if row == table.HeaderRow {
return t.style.HeaderStyle
}
if row%2 == 0 {
return t.style.CellStyle.Background(lipgloss.Color("235"))
}
return t.style.CellStyle
})
}
// Render prints the table to stdout.
func (t *Table) Render() {
if t.headless {
t.renderPlain()
return
}
fmt.Println(t.buildTable())
}
// renderPlain outputs a simple text table for headless mode.
func (t *Table) renderPlain() {
fmt.Println(strings.Join(t.headers, "\t"))
for _, row := range t.rows {
fmt.Println(strings.Join(row, "\t"))
}
}
// String returns the table as a string.
func (t *Table) String() string {
if t.headless {
var sb strings.Builder
sb.WriteString(strings.Join(t.headers, "\t"))
sb.WriteString("\n")
for _, row := range t.rows {
sb.WriteString(strings.Join(row, "\t"))
sb.WriteString("\n")
}
return sb.String()
}
return t.buildTable().String()
}
// RenderToWriter writes the table to the given writer.
func (t *Table) RenderToWriter(w io.Writer) {
_, _ = fmt.Fprintln(w, t.String())
}
================================================
FILE: internal/ui/table_test.go
================================================
package ui
import (
"bytes"
"strings"
"testing"
)
func TestTableAppend(t *testing.T) {
u := newTestUI(t, true)
tbl := NewTable(u, "ID", "NAME")
tbl.Append([]string{"1", "test-server"})
tbl.Append([]string{"2", "other-server"})
if got := len(tbl.rows); got != 2 {
t.Errorf("got %d rows, want 2", got)
}
}
func TestTableString(t *testing.T) {
tests := []struct {
name string
headless bool
headers []string
rows [][]string
wantAll []string
}{
{
name: "headless tab-separated output",
headless: true,
headers: []string{"ID", "NAME", "REGION"},
rows: [][]string{
{"abc-123", "my-server", "fra1"},
{"def-456", "other-server", "lon1"},
},
wantAll: []string{
"ID\tNAME\tREGION",
"abc-123\tmy-server\tfra1",
"def-456\tother-server\tlon1",
},
},
{
name: "interactive styled output",
headless: false,
headers: []string{"ID", "NAME"},
rows: [][]string{{"1", "test"}},
wantAll: []string{"ID", "NAME", "test"},
},
{
name: "empty table with headers only",
headless: true,
headers: []string{"ID", "NAME"},
rows: nil,
wantAll: []string{"ID\tNAME"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
u := newTestUI(t, tt.headless)
tbl := NewTable(u, tt.headers...)
for _, row := range tt.rows {
tbl.Append(row)
}
result := tbl.String()
for _, want := range tt.wantAll {
if !strings.Contains(result, want) {
t.Errorf("output missing %q\ngot: %q", want, result)
}
}
})
}
}
func TestTableRenderToWriter(t *testing.T) {
u := newTestUI(t, true)
tbl := NewTable(u, "ID", "NAME")
tbl.Append([]string{"1", "test"})
var buf bytes.Buffer
tbl.RenderToWriter(&buf)
if !strings.Contains(buf.String(), "1\ttest") {
t.Errorf("RenderToWriter output missing expected content, got %q", buf.String())
}
}
func TestDefaultTableStyle(t *testing.T) {
style := DefaultTableStyle()
if !style.HeaderStyle.GetBold() {
t.Error("expected header style to be bold")
}
}
================================================
FILE: internal/ui/ui.go
================================================
package ui
import (
"fmt"
"github.com/charmbracelet/lipgloss"
"github.com/dirien/minectl/internal/logging"
"go.uber.org/zap"
)
var (
infoStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("12"))
successStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("10"))
errorStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("9"))
warnStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("11"))
)
// UI provides a unified interface for terminal output that handles both
// interactive and headless modes. In interactive mode, it uses Charm components
// for polished output. In headless mode, it falls back to structured logging.
type UI struct {
headless bool
logging *logging.MinectlLogging
}
// NewUI creates a new UI instance.
func NewUI(headless bool, log *logging.MinectlLogging) *UI {
return &UI{
headless: headless,
logging: log,
}
}
// IsHeadless returns true if the UI is running in headless mode (CI/CD).
func (u *UI) IsHeadless() bool {
return u.headless
}
// Logging returns the underlying logging instance.
func (u *UI) Logging() *logging.MinectlLogging {
return u.logging
}
// Info prints an informational message with a dim/neutral style.
func (u *UI) Info(msg string) {
if u.headless {
zap.S().Infow(msg)
return
}
fmt.Println(infoStyle.Render("ℹ " + msg))
}
// Success prints a success message with a green checkmark prefix.
func (u *UI) Success(msg string) {
if u.headless {
zap.S().Infow(msg)
return
}
fmt.Println(successStyle.Render("✓ " + msg))
}
// ErrorMsg prints an error message with a red cross prefix.
func (u *UI) ErrorMsg(err error) {
if u.headless {
zap.S().Errorw(err.Error())
return
}
fmt.Println(errorStyle.Render("✗ " + err.Error()))
}
// Warn prints a warning message with a yellow warning prefix.
func (u *UI) Warn(msg string) {
if u.headless {
zap.S().Warnw(msg)
return
}
fmt.Println(warnStyle.Render("⚠ " + msg))
}
================================================
FILE: internal/ui/ui_test.go
================================================
package ui
import (
"errors"
"testing"
)
func TestUI(t *testing.T) {
tests := []struct {
name string
headless bool
}{
{"headless mode", true},
{"interactive mode", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
u := newTestUI(t, tt.headless)
if got := u.IsHeadless(); got != tt.headless {
t.Errorf("IsHeadless() = %v, want %v", got, tt.headless)
}
if u.Logging() == nil {
t.Error("Logging() returned nil")
}
})
}
}
func TestInfo(t *testing.T) {
tests := []struct {
name string
headless bool
}{
{"headless info", true},
{"interactive info", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
u := newTestUI(t, tt.headless)
// Should not panic
u.Info("test message")
})
}
}
func TestSuccess(t *testing.T) {
tests := []struct {
name string
headless bool
}{
{"headless success", true},
{"interactive success", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
u := newTestUI(t, tt.headless)
// Should not panic
u.Success("server created")
})
}
}
func TestErrorMsg(t *testing.T) {
tests := []struct {
name string
headless bool
}{
{"headless error", true},
{"interactive error", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
u := newTestUI(t, tt.headless)
// Should not panic
u.ErrorMsg(errors.New("something went wrong"))
})
}
}
func TestWarn(t *testing.T) {
tests := []struct {
name string
headless bool
}{
{"headless warn", true},
{"interactive warn", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
u := newTestUI(t, tt.headless)
// Should not panic
u.Warn("this is a warning")
})
}
}
================================================
FILE: main.go
================================================
package main
import (
"fmt"
"os"
"github.com/dirien/minectl/cmd/minectl"
)
var (
version string
commit string
date string
)
func main() {
if err := minectl.Execute(version, commit, date); err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
}
}
================================================
FILE: minectl-skill/SKILL.md
================================================
---
name: minectl
description: "Use this skill for every message containing the word \"minectl\". Claude has zero built-in knowledge of minectl — it is an obscure, third-party CLI for deploying Minecraft servers to cloud providers. Without this skill, any response about minectl will be fabricated. This covers all minectl topics: manifests, create/delete/update commands, RCON troubleshooting, authentication errors, cloud provider selection, instance sizing, budget optimization, TPS tuning, plugin uploads, and edition choice. Do NOT trigger for Minecraft servers managed via Docker, Kubernetes, Ansible, Terraform, or Pulumi — only for minectl-based workflows."
---
# minectl
minectl creates and manages Minecraft servers on 15 cloud providers via declarative YAML manifests.
## Creating a Manifest
Every operation starts with a manifest file:
```yaml
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer
metadata:
name: my-minecraft
spec:
server:
cloud: hetzner
region: fsn1
size: cx21
ssh:
port: 22
publickeyfile: ~/.ssh/id_rsa.pub
fail2ban:
bantime: 1000
maxretry: 3
port: 25565
minecraft:
java:
openjdk: 21
xmx: 2G
xms: 2G
rcon:
password: changeme
port: 25575
enabled: true
edition: papermc
version: "1.21"
eula: true
properties: |
max-players=20
difficulty=normal
motd=My Minecraft Server
```
### Choosing an Edition
| Edition | Best for |
|---------|----------|
| `java` | Vanilla experience, no mods |
| `papermc` | Performance + plugin support (recommended) |
| `spigot` | Bukkit plugin ecosystem |
| `craftbukkit` | Legacy Bukkit plugins |
| `fabric` | Lightweight mods |
| `forge` | Large mod packs |
| `purpur` | Paper + extra gameplay tweaks |
| `bedrock` | Cross-platform (mobile/console/PC) |
| `nukkit` | Java-based Bedrock server |
| `powernukkit` | Extended Nukkit |
For proxy setups, use `kind: MinecraftProxy` with editions: `bungeecord`, `waterfall`, or `velocity`.
### Edition-Specific Tuning
Different editions need different server.properties and resource allocations. Getting these wrong causes crashes, kicks, or poor performance — this is where most new server admins struggle.
**Forge / Fabric (modded servers):**
- Set `max-tick-time=90000` (or `-1` to disable). Modded servers regularly exceed the default 60s watchdog, especially during chunk generation or mod initialization. Leaving the default causes the server to kill itself under normal modded load.
- Set `allow-flight=true`. Many mods (Botania, Mekanism jetpacks, Elytra mods, etc.) trigger the vanilla flight detection. Without this, modded players get kicked constantly.
- Allocate generous heap: 8G minimum for light mods, 12G+ for heavy packs (100+ mods). Set `xms` equal to `xmx` to avoid expensive heap resizing under load.
- Always add `volumeSize: 50` (or more). Mod packs, world data with modded chunks, and backups consume significant disk. Running out of disk silently corrupts worlds.
- Upload mods to `/minecraft/mods` (not `/minecraft/plugins`).
- Enable monitoring (`monitoring.enabled: true`) — modded servers are resource-hungry and benefit from Prometheus metrics to catch memory/CPU issues early.
**PaperMC / Spigot / CraftBukkit / Purpur (plugin servers):**
- Default `max-tick-time=60000` is usually fine.
- Keep `allow-flight=false` unless a specific plugin requires it.
- 2-4G heap is sufficient for up to 20 players with typical plugins.
- Upload plugins to `/minecraft/plugins`.
- PaperMC is the recommended default — it's the most performant fork and supports all Bukkit/Spigot plugins.
**Bedrock / Nukkit / PowerNukkit:**
- No `java` block needed in the manifest (Bedrock is a native binary, not Java-based).
- Default port is `19132` (UDP), not `25565`.
- RCON is not available for Bedrock edition.
- Lower resource requirements: 1-2G RAM is typically sufficient.
### Instance Sizing Guide
| Use case | Players | Recommended RAM | Example sizes |
|----------|---------|----------------|---------------|
| Vanilla / Paper (casual) | 1-10 | 2-4 GB | Hetzner cx21, DO s-2vcpu-4gb |
| Paper with plugins | 10-20 | 4-8 GB | Hetzner cpx31, DO s-4vcpu-8gb, AWS t3.large |
| Forge/Fabric (light mods) | 1-10 | 8 GB | AWS t3.xlarge, Hetzner cpx41 |
| Forge/Fabric (heavy mods) | 5-15 | 16 GB+ | AWS m5.xlarge, Hetzner cpx51 |
| Proxy (BungeeCord/Velocity) | N/A | 1-2 GB | Smallest available |
When using spot instances (`spot: true`), prefer regions with large capacity pools (e.g., `us-east-1` for AWS) to minimize interruption risk. Always warn users that spot instances can be terminated with 2 minutes notice — world backups are essential.
### Security Recommendations
Always include these in every manifest:
- `fail2ban` block under SSH config (prevents brute-force attacks)
- Strong RCON password (never deploy with "changeme")
- Consider `white-list=true` and `enforce-whitelist=true` for private servers
- `online-mode=true` to verify player accounts (prevents unauthorized access)
### Optional Features
Add to `spec.server`:
- `spot: true` - Spot/preemptible instances (AWS, Azure, GCE) to save cost
- `arm: true` - ARM instances (Hetzner, AWS, GCE)
- `volumeSize: 50` - Extra storage in GB
Add to `spec`:
- `monitoring: { enabled: true }` - Prometheus + Node Exporter
### Naming Rules
- `metadata.name` must be lowercase alphanumeric with hyphens only
- SSH port must be 22 or between 1024-65535
- `eula` must be `true`
## Server Lifecycle
```bash
# Generate a manifest interactively
minectl wizard
# Create a server (waits for startup by default)
minectl create -f server.yaml
# Verify the server is running after creation
minectl list -p hetzner -r fsn1
# Expected: server appears with a valid ID and status. If absent, check credentials and quota.
# List running servers
minectl list -p hetzner -r fsn1
# Connect via RCON for remote commands
minectl rcon -f server.yaml --id
# Upload a plugin
minectl plugins -f server.yaml --id -k ~/.ssh/id_rsa \
-p myplugin.jar -d /minecraft/plugins
# Update Minecraft version (edit version in manifest first)
minectl update -f server.yaml --id -k ~/.ssh/id_rsa
# Delete the server
minectl delete -f server.yaml --id -y
```
### Error Recovery
| Symptom | Likely cause | Action |
|---------|--------------|--------|
| `create` exits without a server ID | Authentication failure | Verify provider environment variables are exported (see [references/cloud-providers.md](references/cloud-providers.md)) |
| `create` fails with quota/limit error | Cloud account quota exceeded | Switch region, use a smaller `size`, or request a quota increase from the provider |
| `create` succeeds but server absent from `list` | Wrong region or provider flag | Re-run `minectl list` with the exact `-p` and `-r` values from the manifest |
| Plugin upload fails | SSH key mismatch | Confirm `-k` points to the private key matching `spec.server.ssh.publickeyfile` |
| RCON connection refused | RCON not enabled or wrong port | Ensure `rcon.enabled: true` and the port in the manifest matches `rcon.port` |
## Cloud Provider Selection
When helping a user choose a provider, consider:
- **Budget**: Civo, Hetzner, and DigitalOcean are cheapest. Use `spot: true` on AWS/Azure/GCE for savings.
- **Region needs**: Check [references/cloud-providers.md](references/cloud-providers.md) for available regions.
- **Local testing**: Use `multipass` for local VMs with no cloud account needed.
Each provider requires specific environment variables for authentication. See [references/cloud-providers.md](references/cloud-providers.md) for the full list.
## References
- **Cloud providers, credentials, and sizes**: [references/cloud-providers.md](references/cloud-providers.md)
- **Full manifest schema**: [references/manifest-schema.md](references/manifest-schema.md)
- **CLI command flags and details**: [references/cli-commands.md](references/cli-commands.md)
================================================
FILE: minectl-skill/evals/evals.json
================================================
{
"skill_name": "minectl",
"evals": [
{
"id": 1,
"prompt": "I want to set up a Minecraft server for my kids on Hetzner. We need PaperMC because they want to install some plugins, maybe 10 players max. We're in Europe so something close would be nice. Can you write me the manifest yaml file? Also make sure RCON is enabled so I can manage it remotely. Budget is tight so keep the instance small.",
"expected_output": "A valid minectl YAML manifest with: kind MinecraftServer, cloud hetzner, a European region, edition papermc, RCON enabled, appropriate instance size, eula true, security hardening, and server.properties with max-players=10",
"files": [],
"expectations": [
"Output contains a valid YAML manifest with apiVersion: minectl.ediri.io/v1alpha1",
"The manifest uses kind: MinecraftServer",
"The cloud provider is set to hetzner",
"The region is a European Hetzner region (fsn1, nbg1, or hel1)",
"The edition is set to papermc",
"RCON is enabled with rcon.enabled: true under the java section",
"An rcon.password is set to a non-empty value",
"An rcon.port is specified (typically 25575)",
"The eula field is set to true",
"The server.properties includes max-players=10 or a small player count",
"An SSH public key path is included in the manifest",
"The instance size is a smaller Hetzner size (cx21, cx22, cpx11, or similar)",
"A fail2ban block is included under the ssh section for security",
"The response mentions white-list=true or recommends whitelisting for a kids server",
"The response mentions the plugin upload path is /minecraft/plugins for PaperMC"
]
},
{
"id": 2,
"prompt": "I'm running a modded Minecraft server for my friends using Forge and I want to move it to AWS. We're in the US, about 8 players but heavy mods so we need decent resources. I also want to use spot instances to save money. Can you generate the minectl manifest and tell me what commands I need to run to get it deployed?",
"expected_output": "A manifest with cloud aws, US region, edition forge, spot true, Forge-specific tuning (max-tick-time raised, allow-flight true), generous heap, volumeSize, and correct CLI commands",
"files": [],
"expectations": [
"Output contains a valid YAML manifest with apiVersion: minectl.ediri.io/v1alpha1",
"The cloud provider is set to aws",
"The region is a US-based AWS region (e.g., us-east-1, us-west-2)",
"The edition is set to forge",
"spot: true is included in the server spec",
"The instance size is adequate for modded play (not t2.micro/t3.micro/t3.small)",
"Java heap settings xmx and xms are set to at least 8G for heavy modded play",
"The output includes the minectl create command with -f flag",
"The output mentions AWS credentials or environment variables needed",
"The eula field is set to true",
"max-tick-time is raised above the default 60000 (e.g., 90000 or -1) to prevent watchdog kills with mods",
"allow-flight is set to true to prevent modded players from being kicked",
"volumeSize is included in the server spec for mod pack storage",
"The response mentions uploading mods to /minecraft/mods (not /minecraft/plugins)",
"The response warns about spot instance interruption risk and recommends backups"
]
},
{
"id": 3,
"prompt": "I created a Minecraft server with minectl but I can't connect via RCON. The server is running on DigitalOcean and I used the java edition. What could be wrong and how do I fix it? Here's my manifest:\n\napiVersion: minectl.ediri.io/v1alpha1\nkind: MinecraftServer\nmetadata:\n name: my-server\nspec:\n server:\n cloud: do\n region: fra1\n size: s-4vcpu-8gb\n ssh:\n port: 22\n publickeyfile: ~/.ssh/id_rsa.pub\n port: 25565\n minecraft:\n java:\n openjdk: 21\n xmx: 2G\n xms: 2G\n edition: java\n version: \"1.21\"\n eula: true",
"expected_output": "Diagnosis that RCON is not enabled in the manifest, with a corrected manifest and instructions to update the server",
"files": [],
"expectations": [
"The response correctly identifies that RCON is not enabled/configured in the manifest",
"The response explains that an rcon block is needed under spec.minecraft.java",
"A corrected manifest is provided with rcon.enabled: true",
"The corrected manifest includes an rcon.password field with a value",
"The corrected manifest includes rcon.port (typically 25575)",
"The response mentions using minectl update or minectl delete + create to apply changes",
"The response references the minectl rcon command for connecting after the fix",
"The corrected manifest includes a fail2ban block under ssh (missing from original)",
"The response warns to change the RCON password from the placeholder before deploying"
]
}
]
}
================================================
FILE: minectl-skill/references/cli-commands.md
================================================
# CLI Command Reference
## Global Flags
```
--verbose Logging level: debug|info|warn|error|dpanic|panic|fatal
--log-encoding Log format: console|json (default: console)
--headless CI mode: enables logging, disables interactive output
```
## Commands
### create
Create a Minecraft server from a manifest file.
```bash
minectl create -f [--wait=true]
```
| Flag | Short | Description |
|------|-------|-------------|
| `--filename` | `-f` | Path to manifest YAML file (required) |
| `--wait` | `-w` | Wait for server startup (default: true) |
Output: table with ID, NAME, REGION, TAGS, IP.
### delete
Delete an existing Minecraft server.
```bash
minectl delete -f --id [-y]
```
| Flag | Short | Description |
|------|-------|-------------|
| `--filename` | `-f` | Path to manifest YAML file (required) |
| `--id` | | Server ID (required) |
| `--yes` | `-y` | Skip confirmation prompt |
### list
List all Minecraft servers for a provider/region.
```bash
minectl list -p [-r ]
```
| Flag | Short | Description |
|------|-------|-------------|
| `--provider` | `-p` | Cloud provider name (required) |
| `--region` | `-r` | Region filter (required for civo, gce) |
### update
Update Minecraft version on an existing server via SSH.
```bash
minectl update -f --id -k
```
| Flag | Short | Description |
|------|-------|-------------|
| `--filename` | `-f` | Path to manifest YAML file (required) |
| `--id` | | Server ID (required) |
| `--ssh-key` | `-k` | Path to SSH private key (required) |
### rcon
Connect to a server's RCON port for remote commands.
```bash
minectl rcon -f --id
```
| Flag | Short | Description |
|------|-------|-------------|
| `--filename` | `-f` | Path to manifest YAML file (required) |
| `--id` | | Server ID (required) |
Opens an interactive RCON shell. RCON must be enabled in the manifest.
### plugins
Upload plugins/mods to a running server (beta).
```bash
minectl plugins -f --id -k -p -d
```
| Flag | Short | Description |
|------|-------|-------------|
| `--filename` | `-f` | Path to manifest YAML file (required) |
| `--id` | | Server ID (required) |
| `--ssh-key` | `-k` | Path to SSH private key (required) |
| `--plugin` | `-p` | Path to plugin JAR file |
| `--destination` | `-d` | Server-side destination folder (e.g., `/minecraft/plugins`) |
### wizard
Interactive questionnaire to generate a manifest file.
```bash
minectl wizard [-o ]
```
| Flag | Short | Description |
|------|-------|-------------|
| `--output` | `-o` | Output directory (default: `~/.minectl`) |
### version
Display version information.
```bash
minectl version
```
## Typical Workflow
```bash
# 1. Generate manifest interactively
minectl wizard -o ./configs
# 2. Create server
minectl create -f ./configs/config-my-server.yaml
# 3. Connect via RCON
minectl rcon -f ./configs/config-my-server.yaml --id
# 4. Upload a plugin
minectl plugins -f ./configs/config-my-server.yaml --id \
-k ~/.ssh/id_rsa -p ./myplugin.jar -d /minecraft/plugins
# 5. Update Minecraft version (edit manifest version first)
minectl update -f ./configs/config-my-server.yaml --id -k ~/.ssh/id_rsa
# 6. Delete when done
minectl delete -f ./configs/config-my-server.yaml --id -y
```
================================================
FILE: minectl-skill/references/cloud-providers.md
================================================
# Cloud Provider Reference
## Supported Providers and Environment Variables
| Provider | `cloud` value | Required Environment Variables |
|----------|--------------|-------------------------------|
| Civo | `civo` | `CIVO_TOKEN` |
| Scaleway | `scaleway` | `ACCESS_KEY`, `SECRET_KEY`, `ORGANISATION_ID` |
| DigitalOcean | `do` | `DIGITALOCEAN_TOKEN` |
| Hetzner | `hetzner` | `HCLOUD_TOKEN` |
| Akamai (Linode) | `akamai` | `LINODE_TOKEN` |
| OVHcloud | `ovh` | `OVH_ENDPOINT`, `APPLICATION_KEY`, `APPLICATION_SECRET`, `CONSUMER_KEY`, `SERVICENAME` |
| Google Compute Engine | `gce` | `GOOGLE_PROJECT`, `GOOGLE_SERVICE_ACCOUNT_EMAIL`, `GOOGLE_APPLICATION_CREDENTIALS` (optional, uses ADC) |
| Vultr | `vultr` | `VULTR_API_KEY` |
| Azure | `azure` | `AZURE_SUBSCRIPTION_ID` (uses DefaultAzureCredential) |
| Oracle Cloud (OCI) | `oci` | OCI SDK config (default) |
| AWS | `aws` | Standard AWS SDK credentials |
| VEXXHOST | `vexxhost` | OpenStack env vars |
| Exoscale | `exoscale` | `EXOSCALE_API_KEY`, `EXOSCALE_API_SECRET` |
| Fuga Cloud | `fuga` | OpenStack env vars |
| Ubuntu Multipass | `multipass` | None (local) |
## Region Examples
| Provider | Example Regions |
|----------|----------------|
| Civo | `LON1`, `NYC1`, `FRA1` |
| DigitalOcean | `fra1`, `nyc1`, `sfo1` |
| Hetzner | `fsn1`, `nbg1`, `hel1` |
| AWS | `eu-central-1`, `us-east-1`, `ap-southeast-1` |
| GCE | `europe-west6-a`, `us-central1-a` |
| Azure | `westeurope`, `eastus` |
| Scaleway | `fr-par-1`, `nl-ams-1` |
## Size Examples
| Provider | Example Sizes |
|----------|--------------|
| Civo | `g3.large`, `g3.xlarge` |
| DigitalOcean | `s-4vcpu-8gb` |
| Hetzner | `cx21`, `cpx31` |
| AWS | `t3.xlarge`, `m5.large` |
| GCE | `e2-standard-2`, `e2-standard-4` |
| Azure | `Standard_B2s` |
## Features by Provider
- **Spot instances**: AWS (`spot: true`), Azure (`spot: true`), GCE (`spot: true`)
- **ARM support**: Hetzner (`arm: true`), AWS (`arm: true`), GCE (`arm: true`)
- **Volumes**: All providers support `volumeSize` (in GB)
================================================
FILE: minectl-skill/references/manifest-schema.md
================================================
# Manifest Schema Reference
## MinecraftServer Manifest
```yaml
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftServer # or MinecraftProxy
metadata:
name: # lowercase alphanumeric and hyphens only
spec:
monitoring:
enabled: # optional, enables Prometheus + Node Exporter
server:
cloud: # required: civo|do|hetzner|aws|gce|azure|scaleway|akamai|ovh|vultr|oci|vexxhost|exoscale|fuga|multipass
region: # provider-specific region/zone
size: # provider-specific instance size
volumeSize: # optional, additional volume in GB
arm: # optional, use ARM instances
spot: # optional, use spot/preemptible instances (AWS/Azure/GCE)
ssh:
port: # SSH port (22 or 1024-65535)
publickeyfile: # path to SSH public key file
# OR
publickey: # inline SSH public key
fail2ban:
bantime: # ban duration in seconds
maxretry: # max failed attempts before ban
ignoreip: # optional, IPs to whitelist
port: # Minecraft server port (default 25565)
minecraft:
java: # required for Java editions
openjdk: # OpenJDK version: 8, 16, 17, 21
xmx: # max heap (e.g., "2G")
xms: # initial heap (e.g., "2G")
options: [] # optional, extra JVM flags
rcon:
password: # RCON password
port: # RCON port (default 25575)
enabled: # enable RCON
broadcast: # broadcast RCON to ops
edition: # required: java|papermc|spigot|craftbukkit|fabric|forge|purpur|bedrock|nukkit|powernukkit
version: # required: Minecraft version (e.g., "1.21", "1.20.4-388")
eula: # required: must be true
properties: | # optional: server.properties content
key=value
```
## MinecraftProxy Manifest
```yaml
apiVersion: minectl.ediri.io/v1alpha1
kind: MinecraftProxy
metadata:
name:
spec:
# same server block as MinecraftServer
proxy:
edition: # bungeecord|waterfall|velocity
version:
java:
openjdk:
xmx:
xms:
```
## Editions
| Edition | Type | Notes |
|---------|------|-------|
| `java` | Vanilla | Official Mojang server |
| `papermc` | Fork | High-performance Spigot fork |
| `spigot` | Fork | CraftBukkit fork with plugin API |
| `craftbukkit` | Fork | Modified server with Bukkit API |
| `fabric` | Modloader | Lightweight mod loader |
| `forge` | Modloader | Popular mod platform |
| `purpur` | Fork | Paper fork with extra features |
| `bedrock` | Bedrock | Cross-platform (no Java config needed) |
| `nukkit` | Bedrock | Java-based Bedrock server |
| `powernukkit` | Bedrock | Nukkit fork |
## Proxy Editions
| Edition | Notes |
|---------|-------|
| `bungeecord` | Original Minecraft proxy |
| `waterfall` | BungeeCord fork by PaperMC |
| `velocity` | Modern, high-performance proxy |
## Validation Rules
- `metadata.name`: must match `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
- `spec.server.ssh.port`: must be 22 or between 1024-65535
- `spec.minecraft.eula`: must be `true`
- `spec.server.cloud`: must be a valid provider name