Skip to content
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
9938bf8
Workaround for https://github.com/firegiant/HeatWaveSupport/issues/73
Cyberboss Mar 15, 2025
bec7952
WIP
Cyberboss Mar 15, 2025
f657c6f
Merge branch 'V7' into 2162-Grpc
Cyberboss Apr 6, 2025
9268196
Breaking config change + some integration tests working
Cyberboss Apr 6, 2025
169d768
Working on isolating transfer controller
Cyberboss Apr 9, 2025
77ec44a
Merge branch 'dev' into 2162-Grpc
Cyberboss Apr 13, 2025
70076a6
More cleanup
Cyberboss Apr 13, 2025
976465b
Request limit for transfer controller is disabled
Cyberboss Apr 13, 2025
78e2805
Remove unused using
Cyberboss Apr 13, 2025
baca51d
Give up and create a dedicated swarm transfer controller
Cyberboss Apr 13, 2025
80c48c0
Redo hosting to work with address/port specifications and add additio…
Cyberboss Apr 16, 2025
3716fea
Remove IIS integration
Cyberboss Apr 16, 2025
41b8b16
Merge branch 'V7' into 2162-Grpc
Cyberboss Apr 16, 2025
152dfb8
Bump swarm protocol version
Cyberboss Apr 16, 2025
94052ab
Fix release build and make BindTest saner
Cyberboss Apr 16, 2025
89ce152
Fix typo in `ICallInvokerFactory`
Cyberboss Apr 16, 2025
9438548
Fix swarm unregistration not being able to happen on nodes
Cyberboss Apr 16, 2025
7b3d0b6
Reimplement swarm unit tests
Cyberboss Apr 16, 2025
90bee92
Minor timeout increases
Cyberboss Apr 16, 2025
ee685e5
Setup rudimentary configuration validation
Cyberboss Apr 16, 2025
0f22c3d
Test clairification
Cyberboss Apr 16, 2025
b2dc94d
Fix tests
Cyberboss Apr 16, 2025
c512dcf
Fix bridge port double bind issue
Cyberboss Apr 17, 2025
66c9f46
Fix duplicate bridge port binding issue
Cyberboss Apr 17, 2025
6d740b2
Add a message to this assert because I can't tell what the hell would…
Cyberboss Apr 17, 2025
f8b09b4
Apparently something is fucky with the CreateSysUser test
Cyberboss Apr 18, 2025
a9fc767
More debugging
Cyberboss Apr 18, 2025
e96a541
More debugging
Cyberboss Apr 18, 2025
76b488b
Merge branch 'V7' into 2162-Grpc
Cyberboss Apr 20, 2025
a1cb5da
Get actual useful data before the Assert fires
Cyberboss Apr 20, 2025
4fc5a81
Fix user creation race condition with raw requests tests
Cyberboss Apr 20, 2025
91b7061
Update this assertion
Cyberboss Apr 20, 2025
8b54bc1
Make this static cause why not?
Cyberboss Apr 21, 2025
a484da5
Try to isolate the cause of the hub failures
Cyberboss Apr 25, 2025
ff340eb
Fix build
Cyberboss Apr 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 31 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,13 +252,34 @@ The latter two are not recommended as they cannot be dynamically changed at runt

#### Manual Configuration

Create an `appsettings.Production.yml` file next to `appsettings.yml`. This will override the default settings in `appsettings.yml` with your production settings. There are a few keys meant to be changed by hosts. The configuration is only read after server statup. To reload it you must restart TGS. This can be done while your game servers are running by using the Administrative restart function (as opposed to an OS service restart). Note these are all case-sensitive:
Create an `appsettings.Production.yml` file next to `appsettings.yml`. This will override the default settings in `appsettings.yml` with your production settings. There are a few keys meant to be changed by hosts. The configuration is only read after server statup. To reload it you must restart TGS. This can be done while your game servers are running by using the Administrative restart function (as opposed to an OS service restart).

##### `HostingSpecification`s

A `HostingSpecification` is an object containing an `IPAddress` and `Port` that specifics what IP endpoint a service listens on. i.e:

```yml
HostingSpecificationsList:
- Port: 1234 # Will listen on any IPv4 Address on port 1234
- IPAddress: 0.0.0.0
Port: 2345 # Same on port 2345
- IPAddress: ::1
Port: 3456 # Will only listen on IPv6 localhost port 3456
- IPAddress: 192.168.1.16
Port: 3456 # Will only listen on 192.168.1.16 port 3456
```

##### Options

Note these are all case-sensitive:

- `General:ConfigVersion`: Suppresses warnings about out of date config versions. You should change this after updating TGS to one with a new config version. The current version can be found on the releases page for your server version.

- `General:MinimumPasswordLength`: Minimum password length requirement for database users.
- `General:ApiEndPoints`: Array of `HostingSpecification`s used to host the public TGS HTTP API.

- `General:MetricsEndPoints`: Array of `HostingSpecification`s used to host prometheus metrics under `/metrics` and health checks under `/health`.

- `General:PrometheusPort`: Port Prometheus metrics are published on under /metrics. This can be set to the same value as the `ApiPort`, just note that accessing it does not require authentication.
- `General:MinimumPasswordLength`: Minimum password length requirement for database users.

- `General:ValidInstancePaths`: Array meant to limit the directories in which instances may be created.

Expand All @@ -272,6 +293,8 @@ Create an `appsettings.Production.yml` file next to `appsettings.yml`. This will

- `General:AdditionalEventScriptsDirectories`: An array of directories that are considered to contain EventScripts alongside instance directories. Working directory for executed scripts will remain the instance EventScripts directory.

- `Session:BridgePort`: Port that game servers will talk back to TGS on over `127.0.0.1`.

- `Session:HighPriorityLiveDreamDaemon`: Boolean controlling if live DreamDaemon instances get set to above normal priority processes.

- `Session:LowPriorityDeploymentProcesses `: Boolean controlling if DreamMaker and API validation DreamDaemon instances get set to below normal priority processes.
Expand Down Expand Up @@ -311,11 +334,13 @@ Create an `appsettings.Production.yml` file next to `appsettings.yml`. This will

- `Swarm:PrivateKey`: Must be a secure string set identically on all swarmed servers.

- `Swarm:ControllerAddress`: Must be set on all swarmed servers that are **not** the controller server and should be an address the controller server may be reached at.
- `Swarm:ControllerAddress`: Must be set on all swarmed servers that are **not** the controller server and should be an address the controller server's **swarm service** may be reached at.

- `Swarm:Address`: Must be set on all swarmed servers. Should be an address the server's **swarm service** can be reached at by other servers in the swarm.

- `Swarm:Address`: Must be set on all swarmed servers. Should be an address the server can be reached at by other servers in the swarm.
- `Swarm:EndPoints`: Array of `HostingSpecification`s the server's swarm service is hosted on.

- `Swarm:PublicAddress`: Should be set on all swarmed servers. Should be an address the server can be reached at by other servers in the swarm.
- `Swarm:PublicAddress`: Should be set on all swarmed servers. Should be an address the server's **HTTP API** can be reached at by end users.

- `Swarm:Identifier`: Must be set uniquely on all swarmed servers. Used to identify the current server. This is also used to select which instances exist on the current machine and should not be changed post-setup.

Expand Down
8 changes: 4 additions & 4 deletions build/Version.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
<Import Project="WebpanelVersion.props" />
<PropertyGroup>
<TgsCoreVersion>7.0.0</TgsCoreVersion>
<TgsConfigVersion>5.7.0</TgsConfigVersion>
<TgsConfigVersion>6.0.0</TgsConfigVersion>
<TgsRestVersion>10.13.0</TgsRestVersion>
<TgsGraphQLVersion>0.6.0</TgsGraphQLVersion>
<TgsCommonLibraryVersion>7.0.0</TgsCommonLibraryVersion>
<TgsApiLibraryVersion>18.0.0</TgsApiLibraryVersion>
<TgsClientVersion>21.0.0</TgsClientVersion>
<TgsApiLibraryVersion>19.0.0</TgsApiLibraryVersion>
<TgsClientVersion>22.0.0</TgsClientVersion>
<TgsDmapiVersion>7.3.3</TgsDmapiVersion>
<TgsInteropVersion>5.10.1</TgsInteropVersion>
<TgsHostWatchdogVersion>1.6.0</TgsHostWatchdogVersion>
<TgsSwarmProtocolVersion>9.0.0</TgsSwarmProtocolVersion>
<TgsSwarmProtocolVersion>10.0.0</TgsSwarmProtocolVersion>
<TgsContainerScriptVersion>1.2.1</TgsContainerScriptVersion>
<TgsNugetNetFramework>netstandard2.0</TgsNugetNetFramework>
<TgsNetMajorVersion>10</TgsNetMajorVersion>
Expand Down
5 changes: 4 additions & 1 deletion build/package/deb/appsettings.GitHub.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ Database:
ConnectionString: Data Source=/home/tgstation-server/tgs.sqlite3;Mode=ReadWriteCreate
General:
ConfigVersion: 4.6.0
ApiPort: 5000
ApiEndPoints:
- Port: 5000
GitHubAccessToken:
SetupWizardMode: Never
ByondTopicTimeout: 5000
Expand All @@ -19,6 +20,8 @@ General:
UserLimit: 100
UserGroupLimit: 25
ValidInstancePaths:
Session:
BridgePort: 5000
FileLogging:
Directory:
Disable: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@
<ItemGroup>
<ProjectReference Include="..\Tgstation.Server.Host.Service.Wix\Tgstation.Server.Host.Service.Wix.wixproj" />
</ItemGroup>
<Target Name="CollectSuggestedVisualStudioComponentIds" />
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@
<ItemGroup>
<ProjectReference Include="..\Tgstation.Server.Host.Service.Wix.Extensions\Tgstation.Server.Host.Service.Wix.Extensions.csproj" />
</ItemGroup>
<Target Name="CollectSuggestedVisualStudioComponentIds" />
</Project>
5 changes: 4 additions & 1 deletion build/package/winget/appsettings.GitHub.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ Database:
ConnectionString: Data Source=/tgs.sqlite3;Mode=ReadWriteCreate
General:
ConfigVersion: 4.6.0
ApiPort: 5000
ApiEndPoints:
- Port: 5000
GitHubAccessToken:
SetupWizardMode: Never
ByondTopicTimeout: 5000
Expand All @@ -19,6 +20,8 @@ General:
UserLimit: 100
UserGroupLimit: 25
ValidInstancePaths:
Session:
BridgePort: 5000
FileLogging:
Directory:
Disable: false
Expand Down
6 changes: 4 additions & 2 deletions src/Tgstation.Server.Api/Models/Internal/SwarmServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace Tgstation.Server.Api.Models.Internal
/// <summary>
/// Information about a server in the swarm.
/// </summary>
public abstract class SwarmServer
public class SwarmServer
{
/// <summary>
/// The public address of the server.
Expand All @@ -29,7 +29,7 @@ public abstract class SwarmServer
/// <summary>
/// Initializes a new instance of the <see cref="SwarmServer"/> class.
/// </summary>
protected SwarmServer()
public SwarmServer()
{
}

Expand All @@ -44,7 +44,9 @@ protected SwarmServer(SwarmServer copy)
throw new ArgumentNullException(nameof(copy));
}

#pragma warning disable CS0618 // Type or member is obsolete
Address = copy.Address;
#pragma warning restore CS0618 // Type or member is obsolete
PublicAddress = copy.PublicAddress;
Identifier = copy.Identifier;
}
Expand Down
9 changes: 1 addition & 8 deletions src/Tgstation.Server.Api/Models/Limits.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System;

namespace Tgstation.Server.Api.Models
namespace Tgstation.Server.Api.Models
{
/// <summary>
/// Sanity limits to prevent users from overloading.
Expand All @@ -26,10 +24,5 @@ public static class Limits
/// Length limit for git commit SHAs.
/// </summary>
public const int MaximumCommitShaLength = 40;

/// <summary>
/// The maximum size for file transfers.
/// </summary>
public const int MaximumFileTransferSize = Int32.MaxValue;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ mutation CreateSystemUserWithPermissionSet($systemIdentifier: String!) {
}
user {
id
name
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
query PageUserIds($first: Int, $after: String) {
query PageUserNames($first: Int, $after: String) {
swarm {
users {
queryableUsers(first: $first, after: $after) {
Expand All @@ -8,7 +8,7 @@ query PageUserIds($first: Int, $after: String) {
}
totalCount
nodes {
id
name
}
}
}
Expand Down
10 changes: 0 additions & 10 deletions src/Tgstation.Server.Host/Components/InstanceFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
using Tgstation.Server.Host.Components.Session;
using Tgstation.Server.Host.Components.Watchdog;
using Tgstation.Server.Host.Configuration;
using Tgstation.Server.Host.Core;
using Tgstation.Server.Host.Database;
using Tgstation.Server.Host.IO;
using Tgstation.Server.Host.Jobs;
Expand Down Expand Up @@ -119,11 +118,6 @@ sealed class InstanceFactory : IInstanceFactory
/// </summary>
readonly IRepositoryManagerFactory repositoryManagerFactory;

/// <summary>
/// The <see cref="IServerPortProvider"/> for the <see cref="InstanceFactory"/>.
/// </summary>
readonly IServerPortProvider serverPortProvider;

/// <summary>
/// The <see cref="IFileTransferTicketProvider"/> for the <see cref="InstanceFactory"/>.
/// </summary>
Expand Down Expand Up @@ -187,7 +181,6 @@ sealed class InstanceFactory : IInstanceFactory
/// <param name="networkPromptReaper">The value of <see cref="networkPromptReaper"/>.</param>
/// <param name="platformIdentifier">The value of <see cref="platformIdentifier"/>.</param>
/// <param name="repositoryManagerFactory">The value of <see cref="repositoryManagerFactory"/>.</param>
/// <param name="serverPortProvider">The value of <see cref="serverPortProvider"/>.</param>
/// <param name="fileTransferService">The value of <see cref="fileTransferService"/>.</param>
/// <param name="remoteDeploymentManagerFactory">The value of <see cref="remoteDeploymentManagerFactory"/>.</param>
/// <param name="asyncDelayer">The value of <see cref="asyncDelayer"/>.</param>
Expand All @@ -213,7 +206,6 @@ public InstanceFactory(
INetworkPromptReaper networkPromptReaper,
IPlatformIdentifier platformIdentifier,
IRepositoryManagerFactory repositoryManagerFactory,
IServerPortProvider serverPortProvider,
IFileTransferTicketProvider fileTransferService,
IRemoteDeploymentManagerFactory remoteDeploymentManagerFactory,
IAsyncDelayer asyncDelayer,
Expand All @@ -239,7 +231,6 @@ public InstanceFactory(
this.networkPromptReaper = networkPromptReaper ?? throw new ArgumentNullException(nameof(networkPromptReaper));
this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
this.repositoryManagerFactory = repositoryManagerFactory ?? throw new ArgumentNullException(nameof(repositoryManagerFactory));
this.serverPortProvider = serverPortProvider ?? throw new ArgumentNullException(nameof(serverPortProvider));
this.fileTransferService = fileTransferService ?? throw new ArgumentNullException(nameof(fileTransferService));
this.remoteDeploymentManagerFactory = remoteDeploymentManagerFactory ?? throw new ArgumentNullException(nameof(remoteDeploymentManagerFactory));
this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
Expand Down Expand Up @@ -338,7 +329,6 @@ public async ValueTask<IInstance> CreateInstance(IBridgeRegistrar bridgeRegistra
networkPromptReaper,
platformIdentifier,
bridgeRegistrar,
serverPortProvider,
eventConsumer,
asyncDelayer,
dotnetDumpService,
Expand Down
26 changes: 16 additions & 10 deletions src/Tgstation.Server.Host/Components/InstanceManager.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;

Expand Down Expand Up @@ -32,12 +33,14 @@
namespace Tgstation.Server.Host.Components
{
/// <inheritdoc cref="IInstanceManager" />
#pragma warning disable CA1506 // TODO: Decomplexify
sealed class InstanceManager :
IInstanceManager,
IInstanceCoreProvider,
IHostedService,
IBridgeRegistrar,
IAsyncDisposable
#pragma warning restore CA1506
{
/// <inheritdoc />
public Task Ready => readyTcs.Task;
Expand Down Expand Up @@ -82,11 +85,6 @@ sealed class InstanceManager :
/// </summary>
readonly IAsyncDelayer asyncDelayer;

/// <summary>
/// The <see cref="IServerPortProvider"/> for the <see cref="InstanceManager"/>.
/// </summary>
readonly IServerPortProvider serverPortProvider;

/// <summary>
/// The <see cref="ISwarmServiceController"/> for the <see cref="InstanceManager"/>.
/// </summary>
Expand Down Expand Up @@ -137,6 +135,11 @@ sealed class InstanceManager :
/// </summary>
readonly InternalConfiguration internalConfiguration;

/// <summary>
/// The <see cref="SessionConfiguration"/> for the <see cref="InstanceManager"/>.
/// </summary>
readonly SessionConfiguration sessionConfiguration;

/// <summary>
/// The <see cref="TaskCompletionSource"/> for <see cref="Ready"/>.
/// </summary>
Expand Down Expand Up @@ -183,7 +186,6 @@ sealed class InstanceManager :
/// <param name="serverControl">The value of <see cref="serverControl"/>.</param>
/// <param name="systemIdentityFactory">The value of <see cref="systemIdentityFactory"/>.</param>
/// <param name="asyncDelayer">The value of <see cref="asyncDelayer"/>.</param>
/// <param name="serverPortProvider">The value of <see cref="serverPortProvider"/>.</param>
/// <param name="swarmServiceController">The value of <see cref="swarmServiceController"/>.</param>
/// <param name="console">The value of <see cref="console"/>.</param>
/// <param name="platformIdentifier">The value of <see cref="platformIdentifier"/>.</param>
Expand All @@ -192,6 +194,7 @@ sealed class InstanceManager :
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="generalConfiguration"/>.</param>
/// <param name="swarmConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="swarmConfiguration"/>.</param>
/// <param name="internalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="internalConfiguration"/>.</param>
/// <param name="sessionConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="sessionConfiguration"/>.</param>
/// <param name="logger">The value of <see cref="logger"/>.</param>
public InstanceManager(
IInstanceFactory instanceFactory,
Expand All @@ -202,7 +205,6 @@ public InstanceManager(
IServerControl serverControl,
ISystemIdentityFactory systemIdentityFactory,
IAsyncDelayer asyncDelayer,
IServerPortProvider serverPortProvider,
ISwarmServiceController swarmServiceController,
IConsole console,
IPlatformIdentifier platformIdentifier,
Expand All @@ -211,6 +213,7 @@ public InstanceManager(
IOptions<GeneralConfiguration> generalConfigurationOptions,
IOptions<SwarmConfiguration> swarmConfigurationOptions,
IOptions<InternalConfiguration> internalConfigurationOptions,
IOptions<SessionConfiguration> sessionConfigurationOptions,
ILogger<InstanceManager> logger)
{
this.instanceFactory = instanceFactory ?? throw new ArgumentNullException(nameof(instanceFactory));
Expand All @@ -221,7 +224,6 @@ public InstanceManager(
this.serverControl = serverControl ?? throw new ArgumentNullException(nameof(serverControl));
this.systemIdentityFactory = systemIdentityFactory ?? throw new ArgumentNullException(nameof(systemIdentityFactory));
this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
this.serverPortProvider = serverPortProvider ?? throw new ArgumentNullException(nameof(serverPortProvider));
this.swarmServiceController = swarmServiceController ?? throw new ArgumentNullException(nameof(swarmServiceController));
this.console = console ?? throw new ArgumentNullException(nameof(console));
this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
Expand All @@ -230,6 +232,7 @@ public InstanceManager(
generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions));
swarmConfiguration = swarmConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(swarmConfigurationOptions));
internalConfiguration = internalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(internalConfigurationOptions));
sessionConfiguration = sessionConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(sessionConfigurationOptions));
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));

originalConsoleTitle = console.Title;
Expand Down Expand Up @@ -715,9 +718,12 @@ void PreflightChecks()
}
}

// This runs before the real socket is opened, ensures we don't perform reattaches unless we're fairly certain the bind won't fail
// This runs before the real sockets are opened, ensures we don't perform reattaches unless we're fairly certain the bind won't fail
// If it does fail, DD will be killed.
SocketExtensions.BindTest(platformIdentifier, serverPortProvider.HttpApiPort, true, false);
SocketExtensions.BindTest(platformIdentifier, new IPEndPoint(IPAddress.Loopback, sessionConfiguration.BridgePort), false);
var allHostingSpecs = generalConfiguration.ApiEndPoints.Concat(generalConfiguration.MetricsEndPoints).Concat(swarmConfiguration.EndPoints);
foreach (var hostingSpec in allHostingSpecs)
SocketExtensions.BindTest(platformIdentifier, hostingSpec.ParseIPEndPoint(), false);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ static class DMApiConstants
public const string ParamApiVersion = "server_service_version";

/// <summary>
/// Identifies the <see cref="Core.IServerPortProvider.HttpApiPort"/> of the server.
/// Identifies the bridge port of the server.
/// </summary>
public const string ParamServerPort = "tgs_port";

Expand Down
Loading
Loading