From 80050cbedb590c2b05b9c029967a5c35b9c319c3 Mon Sep 17 00:00:00 2001 From: amadzarak Date: Sat, 25 Apr 2026 22:24:40 -0400 Subject: [PATCH] OPC # 0002: Improvements to Client provisioning workflows --- .../Services/ImageBuildService.cs | 2 +- ControlPlane.Api/Services/TarHelper.cs | 2 ++ ControlPlane.AppHost/AppHost.cs | 2 +- ControlPlane.Worker/Steps/MigrationStep.cs | 8 +++---- infra/dnsmasq/dnsmasq.conf | 10 ++++++++ infra/nginx/nginx.conf | 24 +++++++++++++++++++ 6 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 infra/dnsmasq/dnsmasq.conf create mode 100644 infra/nginx/nginx.conf diff --git a/ControlPlane.Api/Services/ImageBuildService.cs b/ControlPlane.Api/Services/ImageBuildService.cs index 90a6275..00f0395 100644 --- a/ControlPlane.Api/Services/ImageBuildService.cs +++ b/ControlPlane.Api/Services/ImageBuildService.cs @@ -55,7 +55,7 @@ public class ImageBuildService( using var docker = new DockerClientConfiguration(new Uri(socketUri)).CreateClient(); var (repo, tag) = SplitImageTag(ImageName); - var dockerfilePath = "Clarity.Server/Dockerfile"; + var dockerfilePath = "Clarity/Clarity.Server/Dockerfile"; void Log(string line) { onLine(line); record.Log.Add(line); } diff --git a/ControlPlane.Api/Services/TarHelper.cs b/ControlPlane.Api/Services/TarHelper.cs index 4639ac4..17c277c 100644 --- a/ControlPlane.Api/Services/TarHelper.cs +++ b/ControlPlane.Api/Services/TarHelper.cs @@ -13,6 +13,8 @@ internal static class TarHelper [ ".git", ".vs", ".vscode", "node_modules", "bin", "obj", "VaultData", "*.user", "*.suo", + // Exclude sibling repos — build context is ClarityStack/ root but only Clarity/ is needed + "OPC", "gateway", "ClientAssets", ]; public static void Pack(string root, Stream destination) diff --git a/ControlPlane.AppHost/AppHost.cs b/ControlPlane.AppHost/AppHost.cs index 655908a..02e8ae1 100644 --- a/ControlPlane.AppHost/AppHost.cs +++ b/ControlPlane.AppHost/AppHost.cs @@ -69,7 +69,7 @@ var api = builder.AddProject("controlplane-api") .WaitFor(controlPlaneDb) .WithEnvironment("Gitea__BaseUrl", gitea.GetEndpoint("http")) .WithEnvironment("ClientAssets__Folder", clientAssetsPath) - .WithEnvironment("Docker__RepoRoot", builder.AppHostDirectory.Replace("ControlPlane.AppHost", "").TrimEnd('\\', '/')) + .WithEnvironment("Docker__RepoRoot", Path.GetFullPath(Path.Combine(builder.AppHostDirectory, "..", ".."))) // ClarityStack/ root — needed for Directory.*.props .WithExternalHttpEndpoints(); #endregion diff --git a/ControlPlane.Worker/Steps/MigrationStep.cs b/ControlPlane.Worker/Steps/MigrationStep.cs index 3da7f0c..91f2657 100644 --- a/ControlPlane.Worker/Steps/MigrationStep.cs +++ b/ControlPlane.Worker/Steps/MigrationStep.cs @@ -20,10 +20,10 @@ public class MigrationStep( var job = context.Job; var dbName = TenantDbName(job.Subdomain); - var adminConnStr = config.GetConnectionString("postgres") + var adminConnStr = config.GetConnectionString("platformdb") ?? throw new InvalidOperationException( - "ConnectionStrings:postgres is missing. " + - "Ensure ControlPlane.Worker has .WithReference(postgres) in AppHost."); + "ConnectionStrings:platformdb is missing. " + + "Ensure ControlPlane.Worker appsettings.json has a platformdb connection string."); logger.LogInformation("[{JobId}] Provisioning database '{Db}'.", job.Id, dbName); await CreateDatabaseIfNotExistsAsync(adminConnStr, dbName, cancellationToken); @@ -44,7 +44,7 @@ public class MigrationStep( if (string.IsNullOrWhiteSpace(context.TenantConnectionString)) return; var dbName = TenantDbName(context.Job.Subdomain); - var adminConnStr = config.GetConnectionString("postgres"); + var adminConnStr = config.GetConnectionString("platformdb"); if (string.IsNullOrWhiteSpace(adminConnStr)) return; logger.LogWarning("[{JobId}] Compensating: dropping database '{Db}'.", context.Job.Id, dbName); diff --git a/infra/dnsmasq/dnsmasq.conf b/infra/dnsmasq/dnsmasq.conf new file mode 100644 index 0000000..63d1327 --- /dev/null +++ b/infra/dnsmasq/dnsmasq.conf @@ -0,0 +1,10 @@ +# Resolve *.clarity.test → 127.0.0.1 so browser hits nginx on the host +address=/.clarity.test/127.0.0.1 + +# Don't read /etc/resolv.conf or /etc/hosts +no-resolv +no-hosts + +# Forward everything else to Cloudflare +server=1.1.1.1 +server=1.0.0.1 diff --git a/infra/nginx/nginx.conf b/infra/nginx/nginx.conf new file mode 100644 index 0000000..f2858b7 --- /dev/null +++ b/infra/nginx/nginx.conf @@ -0,0 +1,24 @@ +events { + worker_connections 1024; +} + +http { + # Use Docker embedded DNS so container names resolve dynamically + resolver 127.0.0.11 valid=5s ipv6=off; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent"'; + + access_log /var/log/nginx/access.log main; + error_log /var/log/nginx/error.log warn; + + # HTTP → HTTPS redirect + server { + listen 80 default_server; + return 301 https://$host$request_uri; + } + + # Per-tenant server blocks dropped by provisioning worker + include /etc/nginx/conf.d/*.conf; +}