Documentation ¶
Overview ¶
Copyright © 2020 The k3d Author(s)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Index ¶
- Constants
- Variables
- func GetDefaultObjectName(name string) string
- type AgentOpts
- type Cluster
- type ClusterCreateOpts
- type ClusterDeleteOpts
- type ClusterNetwork
- type ClusterStartOpts
- type CmdFlags
- type ExposureOpts
- type ExternalDatastore
- type ImageImportOpts
- type LifecycleStage
- type LogEvent
- type Node
- type NodeCreateOpts
- type NodeDeleteOpts
- type NodeHook
- type NodeHookAction
- type NodeStartOpts
- type NodeState
- type Registry
- type RegistryExternal
- type Role
- type ServerOpts
Constants ¶
const ( MetalLBVersion = "v0.12.1" MetalLBNamespaceManifest = "https://raw.githubusercontent.com/metallb/metallb/%s/manifests/namespace.yaml" MetalLBManifest = "https://raw.githubusercontent.com/metallb/metallb/%s/manifests/metallb.yaml" )
const ( // NodeWaitForLogMessageRestartWarnTime is the time after which to warn about a restarting container NodeWaitForLogMessageRestartWarnTime = 2 * time.Minute // NodeStatusRestarting defines the status string that signals the node container is restarting NodeStatusRestarting = "restarting" // ClusterStatusRunning cluster running status. ClusterStatusRunning = "Running" // ClusterStatusStopped cluster stopped status. ClusterStatusStopped = "Stopped" // ClusterStatusUnknown cluster unknown status. ClusterStatusUnknown = "Unknown" // StatusRunning instance running status. StatusRunning = "Running" // StatusCreating instance creating status. StatusCreating = "Creating" // StatusMissing instance missing status. StatusMissing = "Missing" // StatusFailed instance failed status. StatusFailed = "Failed" // StatusUpgrading instance upgrading status. StatusUpgrading = "Upgrading" // UsageInfoTitle usage info title. UsageInfoTitle = "=========================== Prompt Info ===========================" // UsageContext usage info context. UsageContext = "Use 'kubectl config use-context %s'" // UsagePods usage info pods. UsagePods = "Use 'kubectl get pods -A' get POD status`" )
const ( MetalLb string = "MetalLB" KubeVip string = "kube-vip" ServiceLb string = "servicelb" IngressAmbassador string = "ambassador" IngressAmbassadorAPI string = "ambassadorApi" IngressHaproxy string = "haproxy" IngressHaproxyName string = "kubernetes-ingress" IngressContour string = "contour" IngressNginx string = "nginx" IngressNginxNmae string = "ingress-nginx" IngressKing string = "king" IngressTraefik string = "traefik" Flannel string = "flannel" Calico string = "calico" Cilium string = "cilium" Vxlan string = "vxlan" None string = "none" IpSec string = "ipsec" HostGw string = "host-gw" WireGuard string = "wireguard" IpIp string = "ipip" Bgp string = "bgp" PresetSingle string = "single" PresetOneMaster string = "one-master" PresetWorker string = "worker" PresetMultyMaster string = "multy-master" )
const ( LabelClusterName string = "k3d.cluster" LabelClusterURL string = "k3d.cluster.url" LabelClusterToken string = "k3d.cluster.token" LabelImageVolume string = "k3d.cluster.imageVolume" LabelNetworkExternal string = "k3d.cluster.network.external" LabelNetwork string = "k3d.cluster.network" LabelNetworkID string = "k3d.cluster.network.id" LabelRole string = "k3d.role" LabelServerAPIPort string = "k3d.server.api.port" LabelServerAPIHost string = "k3d.server.api.host" LabelServerAPIHostIP string = "k3d.server.api.hostIP" LabelServerIsInit string = "k3d.server.init" LabelRegistryHost string = "k3d.registry.host" LabelRegistryHostIP string = "k3d.registry.hostIP" LabelRegistryPortExternal string = "k3s.registry.port.external" LabelRegistryPortInternal string = "k3s.registry.port.internal" )
List of k3d technical label name
const ( DefaultRegistryPort = "5000" DefaultRegistryName = DefaultObjectNamePrefix + "-registry" DefaultRegistriesFilePath = "/etc/rancher/k3s/registries.yaml" DefaultRegistryMountPath = "/var/lib/registry" DefaultDockerHubAddress = "registry-1.docker.io" // Default temporary path for the LocalRegistryHosting configmap, from where it will be applied via kubectl DefaultLocalRegistryHostingConfigmapTempPath = "/tmp/localRegistryHostingCM.yaml" )
Registry Defaults
const BackupDefaultName = "velero"
const BackupDefaultNamespace = "backup"
const BackupDefaultProvider = "aws"
const CertManagerDefaultName = "cert-manager"
const CertManagerDefaultNamespace = "cert-manager"
const CertManagerHelmRepo = "jetstack/cert-manager"
const CertManagerHelmRepoName = "jetstack"
const CertManagerHelmURL = "https://charts.jetstack.io"
const DefaultAPIHost = "0.0.0.0"
DefaultAPIHost defines the default host (IP) for the Kubernetes API
const DefaultAPIPort = "6443"
DefaultAPIPort defines the default Kubernetes API Port
const DefaultAwsRegion = "eu-central-1"
const DefaultClusterName = "k3s-default"
DefaultClusterName specifies the default name used for newly created clusters
const DefaultClusterNameMaxLength = 32
DefaultClusterNameMaxLength specifies the maximal length of a passed in cluster name This restriction allows us to construct an name consisting of <DefaultObjectNamePrefix[3]>-<ClusterName>-<TypeSuffix[5-10]>-<Counter[1-3]> ... and still stay within the 64 character limit (e.g. of docker)
const DefaultConfigDirName = ".k3s" // should end up in $HOME/
DefaultConfigDirName defines the name of the config directory (where we'll e.g. put the kubeconfigs)
const DefaultImageVolumeMountPath = "/k3s/images"
DefaultImageVolumeMountPath defines the mount path inside k3d nodes where we will mount the shared image volume by default
const DefaultK3dInternalHostRecord = "host.k3s.internal"
DefaultK3dInternalHostRecord defines the default /etc/hosts entry for the k3d host
const DefaultK3sImageRepo = "docker.io/rancher/k3s"
DefaultK3sImageRepo specifies the default image repository for the used k3s image
const DefaultKubeconfigPrefix = DefaultObjectNamePrefix + "-kubeconfig"
DefaultKubeconfigPrefix defines the default prefix for kubeconfig files
const DefaultLBImageRepo = "docker.io/rancher/k3d-proxy"
DefaultLBImageRepo defines the default cluster load balancer image
const DefaultObjectNamePrefix = "k3s"
DefaultObjectNamePrefix defines the name prefix for every object created by k3d
const DefaultRegistryImageRepo = "docker.io/library/registry"
DefaultRegistryImageRepo defines the default image used for the k3d-managed registry
const DefaultRegistryImageTag = "2"
DefaultRegistryImageTag defines the default image tag used for the k3d-managed registry
const DefaultToolsImageRepo = "docker.io/rancher/k3d-tools"
DefaultToolsImageRepo defines the default image used for the tools container
const FromFileSecret = "from-file"
const GrafanaAgentCloudDefaultName = "grafana-agent"
const GrafanaAgentCloudDefaultNamespace = "monitoring"
const GrafanaAgentCloudHelmRepo = "grengojbo/grafana-agent-cloud"
const GrafanaAgentCloudHelmRepoName = "grengojbo"
const GrafanaAgentCloudHelmURL = "https://grengojbo.github.io/charts/"
const HaproxyCrdBackend = "https://cdn.haproxy.com/documentation/kubernetes/1.8/crd/backend.yaml"
const HaproxyCrdDefaults = "https://cdn.haproxy.com/documentation/kubernetes/1.8/crd/defaults.yaml"
const HaproxyCrdGlobal = "https://cdn.haproxy.com/documentation/kubernetes/1.8/crd/global.yaml"
const HaproxyDefaultName = "haproxy"
const HaproxyDefaultNamespace = "haproxy-controller"
const HaproxyHelmRepo = "haproxytech/kubernetes-ingress"
const HaproxyHelmRepoName = "haproxytech"
const HaproxyHelmURL = "https://haproxytech.github.io/helm-charts"
const HelmDeleteCommand = "helm delete %s -n %s --kubeconfig %s --kube-context %s"
const HelmListCommand = "helm list -A -o json --kubeconfig %s --kube-context %s"
const HelmRepoAddCommand = "helm repo add %s %s --kubeconfig %s --kube-context %s"
const HelmRepoListCommand = "helm repo list --kubeconfig %s --kube-context %s -o json | jq -r '.[].name'"
const HelmListCommand = "helm list -A -o json"
const HelmRepoUpdateCommand = "helm repo update --kubeconfig %s --kube-context %s"
const IngressDefaultName = "ingress-nginx"
const K3sGetScript = "https://get.k3s.io"
const K3sGetScript = "curl -sfL https://get.k3s.io"
const KubernetesGenericSecret = "generic"
const MonitoringDefaultNamespace = "monitoring"
const NamespaceCreateCommand = "kubectl create namespace %s --kubeconfig %s --context %s"
const NamespaceGetCommand = "kubectl get ns -o=custom-columns='NAME:.metadata.name' --no-headers --kubeconfig %s --context %s"
const NginxDefaultName = "nginx"
const NginxDefaultNamespace = "ingress-nginx"
const NginxGetSvcCommand = "kubectl get svc ingress-nginx-controller -n ingress-nginx"
const NginxHelmRepo = "ingress-nginx/ingress-nginx"
const NginxHelmRepoNane = "ingress-nginx"
const NginxHelmURL = "https://kubernetes.github.io/ingress-nginx"
const SecretCreateCommand = "kubectl create secret %s %s %s --kubeconfig %s --context %s"
const SecretDeleteCommand = "kubectl delete secret %s -n %s --kubeconfig %s --context %s"
const SecretListCommand = "kubectl get secret -n %s --kubeconfig %s --context %s -o json | jq -r '.items[].metadata.name'"
const StringLiteralSecret = "string-literal"
const VeleroDefaultName = "velero"
const VeleroDefaultNamespace = "velero"
const VeleroHelmRepo = "vmware-tanzu/velero"
const VeleroHelmRepoName = "vmware-tanzu"
TODO: add Velero
const VeleroHelmURL = "https://vmware-tanzu.github.io/helm-charts"
const VeleroPluginAwsImage = "velero/velero-plugin-for-aws:v1.4.1"
Variables ¶
var ( InitMasterCommand = "curl -sLS %s | %s K3S_TOKEN='%s' INSTALL_K3S_EXEC='server%s%s' %s sh -" // InitMasterCommand = "curl -sLS %s | %s K3S_TOKEN='%s' INSTALL_K3S_EXEC='server %s --node-external-ip %s %s' %s sh -" JoinMasterCommand = "curl -sLS %s | %s K3S_URL='https://%s:6443' K3S_TOKEN='%s' INSTALL_K3S_EXEC='%s' %s sh -" // curl -sfL https://get.k3s.io | K3S_URL='https://<IP>6443' K3S_TOKEN='<TOKEN>' INSTALL_K3S_CHANNEL='stable' sh -s - --node-label node-role.kubernetes.io/master=true --node-taint key=value:NoExecute JoinAgentCommand = "curl -sfL https://get.k3s.io | K3S_URL='%s' %s %s sh -s -" FileClusterToken = "/var/lib/rancher/k3s/server/node-token" FileEnvServer = "/etc/systemd/system/k3s.service.env" // CatTokenCommand = "cat /var/lib/rancher/k3s/server/node-token" CatCfgCommand = "cat /etc/rancher/k3s/k3s.yaml" DockerCommand = "if ! type docker; then curl -sSL %s | sh - %s; fi" DeployUICommand = "echo \"%s\" | base64 -d | sudo tee \"%s/ui.yaml\"" MasterUninstallCommand = "/usr/local/bin/k3s-uninstall.sh" WorkerUninstallCommand = "/usr/local/bin/k3s-agent-uninstall.sh" DrainCommand = "kubectl drain %s --ignore-daemonsets --delete-local-data --grace-period=30 --timeout=120s" DeleteNodeCommand = "kubectl delete node %s" SetWorkerLabel = "kubectl label --overwrite node %s node-role.kubernetes.io/worker=true" TestExitFile = "test -f %s || echo noFile" )
var AddonsList = []string{"cert-manager", "ingress", "external-dns", "monitoring", "backup"}
var CNIplugins = []string{Flannel, Calico, Cilium}
var CiliumBackends = []string{Vxlan, IpIp, WireGuard}
var ClusterExternalNodeRoles = []Role{ RegistryRole, }
ClusterExternalNodeRoles is a list of roles for nodes that do not belong to a specific cluster
var ClusterInternalNodeRoles = []Role{ ServerRole, AgentRole, LoadBalancerRole, }
ClusterInternalNodeRoles is a list of roles for nodes that belong to a cluster
var DefaultNodeEnv = []string{
"K3S_KUBECONFIG_OUTPUT=/output/kubeconfig.yaml",
}
DefaultNodeEnv defines some default environment variables that should be set on every node
var DefaultObjectLabels = map[string]string{
"app": "k3s",
}
DefaultObjectLabels specifies a set of labels that will be attached to k3d objects by default
var DefaultObjectLabelsVar = map[string]string{ "k3s.version": version.GetVersion(), }
DefaultObjectLabelsVar specifies a set of labels that will be attached to k3d objects by default but are not static (e.g. across k3d versions)
var DefaultRoleCmds = map[Role][]string{ ServerRole: {"server"}, AgentRole: {"agent"}, }
DefaultRoleCmds maps the node roles to their respective default commands
var DefaultTmpfsMounts = []string{
"/run",
"/var/run",
}
DefaultTmpfsMounts specifies tmpfs mounts that are required for all k3d nodes
var DoNotCopyServerFlags = []string{
"--cluster-init",
}
DoNotCopyServerFlags defines a list of commands/args that shouldn't be copied from an existing node when adding a similar node to a cluster
var HelmAddons = []string{"cert-manager"}
var IngressList = []string{IngressHaproxy, IngressNginx}
var IngressControllers = []string{IngressAmbassador, IngressAmbassadorAPI, IngressContour, IngressHaproxyName, IngressHaproxy, IngressKing, IngressNginx, IngressTraefik}
var LoadBalancerList = []string{MetalLb, ServiceLb}
var NodeRoles = map[string]Role{ string(ServerRole): ServerRole, string(AgentRole): AgentRole, string(LoadBalancerRole): LoadBalancerRole, string(RegistryRole): RegistryRole, }
NodeRoles defines the roles available for nodes
var PresetList = []string{PresetSingle, PresetOneMaster, PresetWorker, PresetMultyMaster}
var ReadyLogMessageByRole = map[Role]string{
ServerRole: "k3s is up and running",
AgentRole: "Successfully registered node",
LoadBalancerRole: "start worker processes",
RegistryRole: "listening on",
}
ReadyLogMessageByRole defines the log messages we wait for until a server node is considered ready
Functions ¶
func GetDefaultObjectName ¶
GetDefaultObjectName prefixes the passed name with the default prefix
Types ¶
type AgentOpts ¶
type AgentOpts struct{}
AgentOpts describes some additional agent role specific opts
type Cluster ¶
type Cluster struct { Name string `yaml:"name" json:"name,omitempty"` Network ClusterNetwork `yaml:"network" json:"network,omitempty"` Token string `yaml:"clusterToken" json:"clusterToken,omitempty"` Nodes []*Node `yaml:"nodes" json:"nodes,omitempty"` InitNode *Node // init server node ExternalDatastore *ExternalDatastore `yaml:"externalDatastore,omitempty" json:"externalDatastore,omitempty"` KubeAPI *ExposureOpts `yaml:"kubeAPI" json:"kubeAPI,omitempty"` ServerLoadBalancer *Node `yaml:"serverLoadbalancer,omitempty" json:"serverLoadBalancer,omitempty"` ImageVolume string `yaml:"imageVolume" json:"imageVolume,omitempty"` }
Cluster describes a k3d cluster
func (*Cluster) AgentCountRunning ¶
AgentCountRunning returns the number of agent nodes running in the cluster and the total number
func (*Cluster) HasLoadBalancer ¶
HasLoadBalancer returns true if cluster has a loadbalancer node
func (*Cluster) ServerCountRunning ¶
ServerCountRunning returns the number of server nodes running in the cluster and the total number
type ClusterCreateOpts ¶
type ClusterCreateOpts struct { PrepDisableHostIPInjection bool `yaml:"prepDisableHostIPInjection" json:"prepDisableHostIPInjection,omitempty"` DisableImageVolume bool `yaml:"disableImageVolume" json:"disableImageVolume,omitempty"` WaitForServer bool `yaml:"waitForServer" json:"waitForServer,omitempty"` Timeout time.Duration `yaml:"timeout" json:"timeout,omitempty"` DisableLoadBalancer bool `yaml:"disableLoadbalancer" json:"disableLoadbalancer,omitempty"` K3sServerArgs []string `yaml:"k3sServerArgs" json:"k3sServerArgs,omitempty"` K3sAgentArgs []string `yaml:"k3sAgentArgs" json:"k3sAgentArgs,omitempty"` GPURequest string `yaml:"gpuRequest" json:"gpuRequest,omitempty"` ServersMemory string `yaml:"serversMemory" json:"serversMemory,omitempty"` AgentsMemory string `yaml:"agentsMemory" json:"agentsMemory,omitempty"` NodeHooks []NodeHook `yaml:"nodeHooks,omitempty" json:"nodeHooks,omitempty"` GlobalLabels map[string]string `yaml:"globalLabels,omitempty" json:"globalLabels,omitempty"` GlobalEnv []string `yaml:"globalEnv,omitempty" json:"globalEnv,omitempty"` Registries struct { Create *Registry `yaml:"create,omitempty" json:"create,omitempty"` Use []*Registry `yaml:"use,omitempty" json:"use,omitempty"` Config *k3s.Registry `yaml:"config,omitempty" json:"config,omitempty"` // registries.yaml (k3s config for containerd registry override) } `yaml:"registries,omitempty" json:"registries,omitempty"` }
ClusterCreateOpts describe a set of options one can set when creating a cluster
type ClusterDeleteOpts ¶
type ClusterDeleteOpts struct {
SkipRegistryCheck bool // skip checking if this is a registry (and act accordingly)
}
ClusterDeleteOpts describe a set of options one can set when deleting a cluster
type ClusterNetwork ¶
type ClusterNetwork struct { Name string `yaml:"name" json:"name,omitempty"` External bool `yaml:"external" json:"isExternal,omitempty"` }
ClusterNetwork describes a network which a cluster is running in
type ClusterStartOpts ¶
type ClusterStartOpts struct { WaitForServer bool Timeout time.Duration NodeHooks []NodeHook `yaml:"nodeHooks,omitempty" json:"nodeHooks,omitempty"` }
ClusterStartOpts describe a set of options one can set when (re-)starting a cluster
type ExposureOpts ¶
type ExposureOpts struct { nat.PortMapping // filled automatically (reference to normal portmapping) Host string `yaml:"host,omitempty" json:"host,omitempty"` }
ExposureOpts describes settings that the user can set for accessing the Kubernetes API
type ExternalDatastore ¶
type ExternalDatastore struct { Endpoint string `yaml:"endpoint" json:"endpoint,omitempty"` CAFile string `yaml:"caFile" json:"caFile,omitempty"` CertFile string `yaml:"certFile" json:"certFile,omitempty"` KeyFile string `yaml:"keyFile" json:"keyFile,omitempty"` Network string `yaml:"network" json:"network,omitempty"` }
ExternalDatastore describes an external datastore used for HA/multi-server clusters
type ImageImportOpts ¶
type ImageImportOpts struct {
KeepTar bool
}
ImageImportOpts describes a set of options one can set for loading image(s) into cluster(s)
type LifecycleStage ¶
type LifecycleStage string
LifecycleStage defines descriptors for specific stages in the lifecycle of a node or cluster object
const ( LifecycleStagePreStart LifecycleStage = "preStart" LifecycleStagePostStart LifecycleStage = "postStart" )
all defined lifecyclestages
type Node ¶
type Node struct { Name string `yaml:"name" json:"name,omitempty"` Role Role `yaml:"role" json:"role,omitempty"` Image string `yaml:"image" json:"image,omitempty"` Volumes []string `yaml:"volumes" json:"volumes,omitempty"` Env []string `yaml:"env" json:"env,omitempty"` Cmd []string // filled automatically based on role Args []string `yaml:"extraArgs" json:"extraArgs,omitempty"` Ports nat.PortMap `yaml:"portMappings" json:"portMappings,omitempty"` Restart bool `yaml:"restart" json:"restart,omitempty"` Created string `yaml:"created" json:"created,omitempty"` Labels map[string]string // filled automatically Networks []string // filled automatically ExtraHosts []string // filled automatically ServerOpts ServerOpts `yaml:"serverOpts" json:"serverOpts,omitempty"` AgentOpts AgentOpts `yaml:"agentOpts" json:"agentOpts,omitempty"` GPURequest string // filled automatically Memory string // filled automatically State NodeState // filled automatically }
Node describes a k3d node
type NodeCreateOpts ¶
type NodeCreateOpts struct { Wait bool Timeout time.Duration NodeHooks []NodeHook `yaml:"nodeHooks,omitempty" json:"nodeHooks,omitempty"` }
NodeCreateOpts describes a set of options one can set when creating a new node
type NodeDeleteOpts ¶
type NodeDeleteOpts struct {
SkipLBUpdate bool // skip updating the loadbalancer
}
NodeDeleteOpts describes a set of options one can set when deleting a node
type NodeHook ¶
type NodeHook struct { Stage LifecycleStage `yaml:"stage,omitempty" json:"stage,omitempty"` Action NodeHookAction `yaml:"action,omitempty" json:"action,omitempty"` }
NodeHook is an action that is bound to a specifc stage of a node lifecycle
type NodeHookAction ¶
NodeHookAction is an interface to implement actions that should trigger at specific points of the node lifecycle
type NodeStartOpts ¶
type NodeStartOpts struct { Wait bool Timeout time.Duration NodeHooks []NodeHook `yaml:"nodeHooks,omitempty" json:"nodeHooks,omitempty"` ReadyLogMessage string }
NodeStartOpts describes a set of options one can set when (re-)starting a node
type Registry ¶
type Registry struct { ClusterRef string // filled automatically -> if created with a cluster Protocol string `yaml:"protocol,omitempty" json:"protocol,omitempty"` // default: http Host string `yaml:"host" json:"host"` Image string `yaml:"image,omitempty" json:"image,omitempty"` ExposureOpts ExposureOpts `yaml:"expose" json:"expose"` Options struct { ConfigFile string `yaml:"configFile,omitempty" json:"configFile,omitempty"` Proxy struct { RemoteURL string `yaml:"remoteURL" json:"remoteURL"` Username string `yaml:"username,omitempty" json:"username,omitempty"` Password string `yaml:"password,omitempty" json:"password,omitempty"` } `yaml:"proxy,omitempty" json:"proxy,omitempty"` } `yaml:"options,omitempty" json:"options,omitempty"` }
Registry describes a k3d-managed registry
type RegistryExternal ¶
type RegistryExternal struct { Protocol string `yaml:"protocol,omitempty" json:"protocol,omitempty"` // default: http Host string `yaml:"host" json:"host"` Port string `yaml:"port" json:"port"` }
RegistryExternal describes a minimal spec for an "external" registry "external" meaning, that it's unrelated to the current cluster e.g. used for the --registry-use flag registry reference
type ServerOpts ¶
type ServerOpts struct { IsInit bool `yaml:"isInitializingServer" json:"isInitializingServer,omitempty"` KubeAPI *ExposureOpts `yaml:"kubeAPI" json:"kubeAPI"` }
ServerOpts describes some additional server role specific opts