mirror of
https://github.com/MAKS-IT-COM/maksit-certs-ui.git
synced 2025-12-31 04:00:03 +01:00
(feature): first release
This commit is contained in:
parent
6d10e3af53
commit
b30d7903a5
200
README.md
200
README.md
@ -7,82 +7,36 @@ Simple client to obtain Let's Encrypt HTTPS certificates developed with .net cor
|
|||||||
* 29 Jun, 2019 - V1.0
|
* 29 Jun, 2019 - V1.0
|
||||||
* 01 Nov, 2019 - V2.0 (Dependency Injection pattern impelemtation)
|
* 01 Nov, 2019 - V2.0 (Dependency Injection pattern impelemtation)
|
||||||
* 31 May, 2024 - V3.0 (Webapi and containerization)
|
* 31 May, 2024 - V3.0 (Webapi and containerization)
|
||||||
|
* 11 Aug, 2024 - V3.1 (Release)
|
||||||
|
|
||||||
## Haproxy configuration
|
## Haproxy configuration
|
||||||
|
|
||||||
```bash
|
|
||||||
# Create the user with a normal shell
|
|
||||||
sudo useradd -m -s /bin/bash acme
|
|
||||||
|
|
||||||
# Set the user's password
|
|
||||||
sudo passwd acme
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo passwd acme
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo mkdir /etc/haproxy/certs
|
sudo mkdir /etc/haproxy/certs
|
||||||
chown acme:root /etc/haproxy/certs
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
#---------------------------------------------------------------------
|
sudo nano /etc/haproxy/haproxy.cfg
|
||||||
# Example configuration for a possible web application. See the
|
```
|
||||||
# full configuration options online.
|
|
||||||
#
|
|
||||||
# https://www.haproxy.org/download/1.8/doc/configuration.txt
|
|
||||||
#
|
|
||||||
#---------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
```ini
|
||||||
#---------------------------------------------------------------------
|
#---------------------------------------------------------------------
|
||||||
# Global settings
|
# Global settings
|
||||||
#---------------------------------------------------------------------
|
#---------------------------------------------------------------------
|
||||||
global
|
global
|
||||||
# to have these messages end up in /var/log/haproxy.log you will
|
|
||||||
# need to:
|
|
||||||
#
|
|
||||||
# 1) configure syslog to accept network log events. This is done
|
|
||||||
# by adding the '-r' option to the SYSLOGD_OPTIONS in
|
|
||||||
# /etc/sysconfig/syslog
|
|
||||||
#
|
|
||||||
# 2) configure local2 events to go to the /var/log/haproxy.log
|
|
||||||
# file. A line like the following can be added to
|
|
||||||
# /etc/sysconfig/syslog
|
|
||||||
#
|
|
||||||
# local2.* /var/log/haproxy.log
|
|
||||||
#
|
|
||||||
log 127.0.0.1 local2
|
log 127.0.0.1 local2
|
||||||
|
|
||||||
chroot /var/lib/haproxy
|
chroot /var/lib/haproxy
|
||||||
pidfile /var/run/haproxy.pid
|
pidfile /var/run/haproxy.pid
|
||||||
maxconn 4000
|
maxconn 4000
|
||||||
user haproxy
|
user haproxy
|
||||||
group haproxy
|
group haproxy
|
||||||
daemon
|
daemon
|
||||||
|
stats socket /var/lib/haproxy/stats
|
||||||
# Adjust the maxconn value based on your server\'s capacity
|
|
||||||
maxconn 2048
|
|
||||||
|
|
||||||
# SSL certificates directory
|
|
||||||
# ca-base /etc/ssl/certs
|
|
||||||
#crt-base /etc/ssl/private
|
|
||||||
|
|
||||||
# Default SSL certificate (used if no SNI match)
|
|
||||||
#ssl-default-bind-crt /etc/haproxy/certs/default.pem
|
|
||||||
|
|
||||||
# turn on stats unix socket
|
|
||||||
# stats socket /var/lib/haproxy/stats level admin mode 660
|
|
||||||
#stats socket /var/run/haproxy/admin.sock level admin mode 660 user haproxy group haproxy
|
|
||||||
|
|
||||||
# utilize system-wide crypto-policies
|
|
||||||
ssl-default-bind-ciphers PROFILE=SYSTEM
|
ssl-default-bind-ciphers PROFILE=SYSTEM
|
||||||
ssl-default-server-ciphers PROFILE=SYSTEM
|
ssl-default-server-ciphers PROFILE=SYSTEM
|
||||||
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------
|
#---------------------------------------------------------------------
|
||||||
# common defaults that all the \'listen\' and \'backend\' sections will
|
# common defaults that all the 'listen' and 'backend' sections will
|
||||||
# use if not designated in their block
|
# use if not designated in their block
|
||||||
#---------------------------------------------------------------------
|
#---------------------------------------------------------------------
|
||||||
defaults
|
defaults
|
||||||
@ -103,83 +57,111 @@ defaults
|
|||||||
timeout check 10s
|
timeout check 10s
|
||||||
maxconn 3000
|
maxconn 3000
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------
|
||||||
|
# Frontend for HTTP traffic on port 80
|
||||||
|
#---------------------------------------------------------------------
|
||||||
|
frontend http_frontend
|
||||||
|
bind *:80
|
||||||
|
acl acme_path path_beg /.well-known/acme-challenge/
|
||||||
|
|
||||||
|
# Redirect all HTTP traffic to HTTPS except ACME challenge requests
|
||||||
|
redirect scheme https if !acme_path
|
||||||
|
|
||||||
|
# Use the appropriate backend based on hostname if it's an ACME challenge request
|
||||||
|
use_backend acme_backend if acme_path
|
||||||
|
|
||||||
#---------------------------------------------------------------------
|
#---------------------------------------------------------------------
|
||||||
# Frontend configuration for handling multiple domains with SNI
|
# Backend to handle ACME challenge requests
|
||||||
#---------------------------------------------------------------------
|
#---------------------------------------------------------------------
|
||||||
frontend web
|
backend acme_backend
|
||||||
bind :80
|
server local_acme 127.0.0.1:8080
|
||||||
bind :443 ssl crt /etc/haproxy/certs/ strict-sni
|
|
||||||
|
|
||||||
# Handling for ACME challenge paths
|
|
||||||
acl acme_challenge path_beg /.well-known/acme-challenge/
|
|
||||||
use_backend acme_challenge_backend if acme_challenge
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------
|
#---------------------------------------------------------------------
|
||||||
# Backend configuration for ACME challenge
|
# Frontend for HTTPS traffic (port 443) with SNI and strict-sni
|
||||||
#---------------------------------------------------------------------
|
#---------------------------------------------------------------------
|
||||||
backend acme_challenge_backend
|
frontend https_frontend
|
||||||
server acme_challenge 127.0.0.1:8080
|
bind *:443 ssl crt /etc/haproxy/certs strict-sni
|
||||||
|
|
||||||
|
http-request capture req.hdr(host) len 64
|
||||||
|
|
||||||
|
# Define ACLs for routing based on hostname
|
||||||
|
acl host_git hdr(host) -i git.maks-it.com
|
||||||
|
acl host_cr hdr(host) -i cr.maks-it.com
|
||||||
|
|
||||||
|
# Use appropriate backend based on SNI hostname
|
||||||
|
use_backend git_backend if host_git
|
||||||
|
use_backend cr_backend if host_cr
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------
|
||||||
|
# Backend for git.maks-it.com
|
||||||
|
#---------------------------------------------------------------------
|
||||||
|
backend git_backend
|
||||||
|
http-request set-header X-Forwarded-Proto https
|
||||||
|
http-request set-header X-Forwarded-Host %[hdr(host)]
|
||||||
|
server git_server gitsrv0002.corp.maks-it.com:3000
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------
|
||||||
|
# Backend for cr.maks-it.com
|
||||||
|
#---------------------------------------------------------------------
|
||||||
|
backend cr_backend
|
||||||
|
http-request set-header X-Forwarded-Proto https
|
||||||
|
http-request set-header X-Forwarded-Host %[hdr(host)]
|
||||||
|
server cr_server hcrsrv0001.corp.maks-it.com:80
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------
|
||||||
|
# letsencrypt load balancer
|
||||||
|
#---------------------------------------------------------------------
|
||||||
|
frontend letsencrypt
|
||||||
|
bind *:8080
|
||||||
|
mode http
|
||||||
|
acl path_well_known_acme path_beg /.well-known/acme-challenge/
|
||||||
|
acl path_swagger path_beg /swagger/
|
||||||
|
acl path_api path_beg /api/
|
||||||
|
|
||||||
|
use_backend letsencrypt_server if path_well_known_acme
|
||||||
|
use_backend letsencrypt_server if path_swagger
|
||||||
|
use_backend letsencrypt_server if path_api
|
||||||
|
default_backend letsencrypt_app
|
||||||
|
|
||||||
|
backend letsencrypt_server
|
||||||
|
mode http
|
||||||
|
server server1 127.0.0.1:9000 check
|
||||||
|
|
||||||
|
backend letsencrypt_app
|
||||||
|
mode http
|
||||||
|
server app1 127.0.0.1:3000 check
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## MaksIT agent installation
|
||||||
|
|
||||||
|
From your home directory
|
||||||
|
|
||||||
## MaksIT agent
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
openssl rand -base64 32
|
git clone https://github.com/MAKS-IT-COM/certs-ui.git
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo rpm -Uvh https://packages.microsoft.com/config/centos/8/packages-microsoft-prod.rpm
|
cd certs-ui/src/Agent
|
||||||
sudo dnf install -y dotnet-sdk-8.0
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
Copy sources to
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo mkdir -p /opt/maks-it-agent
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dotnet build --configuration Release
|
|
||||||
dotnet publish -c Release -o /opt/maks-it-agent
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo nano /etc/systemd/system/maks-it-agent.service
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
[Unit]
|
sudo sh ./build_and_deploy.sh
|
||||||
Description=Maks-IT Agent
|
```
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
WorkingDirectory=/opt/maks-it-agent
|
|
||||||
ExecStart=/usr/bin/dotnet /opt/maks-it-agent/Agent.dll --urls "http://*:5000"
|
|
||||||
Restart=always
|
|
||||||
# Restart service after 10 seconds if the dotnet service crashes:
|
|
||||||
RestartSec=10
|
|
||||||
KillSignal=SIGINT
|
|
||||||
SyslogIdentifier=dotnet-servicereloader
|
|
||||||
User=root
|
|
||||||
Environment=ASPNETCORE_ENVIRONMENT=Production
|
|
||||||
|
|
||||||
[Install]
|
## Maks IT LetsEncrypt server installation
|
||||||
WantedBy=multi-user.target
|
|
||||||
|
From your home directory
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/MAKS-IT-COM/certs-ui.git
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo systemctl daemon-reload
|
cd certs-ui/src
|
||||||
sudo systemctl enable --now maks-it-agent.service
|
```
|
||||||
sudo systemctl status maks-it-agent.service
|
|
||||||
|
```bash
|
||||||
|
podman-compose -f docker-compose.final.yml up
|
||||||
```
|
```
|
||||||
|
|||||||
34
pipeline.json
Normal file
34
pipeline.json
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"version": "1.0",
|
||||||
|
"name": "CI/CD Pipeline",
|
||||||
|
"jobs": {
|
||||||
|
"build-and-push": {
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"agent": "kaniko",
|
||||||
|
|
||||||
|
"context": "src",
|
||||||
|
"dockerfile-path": "LetsEncryptServer/Dockerfile",
|
||||||
|
|
||||||
|
"image-name": "${{ env.REGISTRY_URL }}/${{ env.USERNAME }}/certs-ui-server:latest",
|
||||||
|
"username": "${{ env.USERNAME }}",
|
||||||
|
"password": "${{ env.PASSWORD }}"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"agent": "kaniko",
|
||||||
|
|
||||||
|
"context": "src",
|
||||||
|
"dockerfile-path": "ClientApp/Dockerfile",
|
||||||
|
|
||||||
|
"image-name": "${{ env.REGISTRY_URL }}/${{ env.USERNAME }}/certs-ui-clientapp:latest",
|
||||||
|
"username": "${{ env.USERNAME }}",
|
||||||
|
"password": "${{ env.PASSWORD }}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"deploy": {
|
||||||
|
"steps": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,12 +1,14 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.6" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@ -19,5 +21,4 @@
|
|||||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
37
src/Agent/Agent.generated.sln
Normal file
37
src/Agent/Agent.generated.sln
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.5.002.0
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Agent - Backup (1)", "Agent - Backup (1).csproj", "{392E9E34-E17C-4118-9C83-52AF52A56E54}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Agent - Backup", "Agent - Backup.csproj", "{18049E33-180E-41F1-8343-5BCD4755B2A8}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Agent", "Agent.csproj", "{2C1A9C83-0B26-450C-A874-0B8DBD251B0F}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{392E9E34-E17C-4118-9C83-52AF52A56E54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{392E9E34-E17C-4118-9C83-52AF52A56E54}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{392E9E34-E17C-4118-9C83-52AF52A56E54}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{392E9E34-E17C-4118-9C83-52AF52A56E54}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{18049E33-180E-41F1-8343-5BCD4755B2A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{18049E33-180E-41F1-8343-5BCD4755B2A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{18049E33-180E-41F1-8343-5BCD4755B2A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{18049E33-180E-41F1-8343-5BCD4755B2A8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{2C1A9C83-0B26-450C-A874-0B8DBD251B0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{2C1A9C83-0B26-450C-A874-0B8DBD251B0F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{2C1A9C83-0B26-450C-A874-0B8DBD251B0F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{2C1A9C83-0B26-450C-A874-0B8DBD251B0F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {281E7450-1EDC-4E77-B04F-C14F65273D90}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
@ -1,6 +1,29 @@
|
|||||||
namespace MaksIT.Agent {
|
namespace MaksIT.Agent {
|
||||||
public class Configuration {
|
public class Configuration {
|
||||||
public required string ApiKey { get; set; }
|
|
||||||
public required string CertsPath { get; set; }
|
private string? _apiKey;
|
||||||
|
public string ApiKey {
|
||||||
|
get {
|
||||||
|
var env = Environment.GetEnvironmentVariable("MAKS-IT_AGENT_API_KEY");
|
||||||
|
return env ?? _apiKey ?? string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
set {
|
||||||
|
_apiKey = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private string? _certsPath;
|
||||||
|
public string CertsPath {
|
||||||
|
get {
|
||||||
|
var env = Environment.GetEnvironmentVariable("MAKS-IT_AGENT_CERTS_PATH");
|
||||||
|
return env ?? _certsPath ?? string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
set {
|
||||||
|
_certsPath = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,15 +12,20 @@ namespace MaksIT.Agent.Controllers;
|
|||||||
public class CertsController : ControllerBase {
|
public class CertsController : ControllerBase {
|
||||||
|
|
||||||
private readonly Configuration _appSettings;
|
private readonly Configuration _appSettings;
|
||||||
|
private readonly ILogger<CertsController> _logger;
|
||||||
|
|
||||||
public CertsController(
|
public CertsController(
|
||||||
IOptions<Configuration> appSettings
|
IOptions<Configuration> appSettings,
|
||||||
|
ILogger<CertsController> logger
|
||||||
) {
|
) {
|
||||||
|
_logger = logger;
|
||||||
_appSettings = appSettings.Value;
|
_appSettings = appSettings.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("[action]")]
|
[HttpPost("[action]")]
|
||||||
public IActionResult Upload([FromBody] CertsUploadRequest requestData) {
|
public IActionResult Upload([FromBody] CertsUploadRequest requestData) {
|
||||||
|
_logger.LogInformation("Uploading certificates");
|
||||||
|
|
||||||
foreach (var (fileName, fileContent) in requestData.Certs) {
|
foreach (var (fileName, fileContent) in requestData.Certs) {
|
||||||
System.IO.File.WriteAllText(Path.Combine(_appSettings.CertsPath, fileName), fileContent);
|
System.IO.File.WriteAllText(Path.Combine(_appSettings.CertsPath, fileName), fileContent);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,23 +1,14 @@
|
|||||||
{
|
{
|
||||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
|
||||||
"iisSettings": {
|
|
||||||
"windowsAuthentication": false,
|
|
||||||
"anonymousAuthentication": true,
|
|
||||||
"iisExpress": {
|
|
||||||
"applicationUrl": "http://localhost:7748",
|
|
||||||
"sslPort": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"profiles": {
|
"profiles": {
|
||||||
"http": {
|
"http": {
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
"dotnetRunMessages": true,
|
|
||||||
"launchBrowser": true,
|
"launchBrowser": true,
|
||||||
"launchUrl": "swagger",
|
"launchUrl": "swagger",
|
||||||
"applicationUrl": "http://localhost:5000",
|
|
||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
}
|
},
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"applicationUrl": "http://localhost:5000"
|
||||||
},
|
},
|
||||||
"IIS Express": {
|
"IIS Express": {
|
||||||
"commandName": "IISExpress",
|
"commandName": "IISExpress",
|
||||||
@ -26,6 +17,24 @@
|
|||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Container (Dockerfile)": {
|
||||||
|
"commandName": "Docker",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_HTTP_PORTS": "5000"
|
||||||
|
},
|
||||||
|
"publishAllPorts": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:7748",
|
||||||
|
"sslPort": 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -11,7 +11,7 @@ APPSETTINGS_FILE="appsettings.json"
|
|||||||
NO_NEW_KEY_FLAG="--no-new-key"
|
NO_NEW_KEY_FLAG="--no-new-key"
|
||||||
|
|
||||||
# Update package index and install the Microsoft package repository
|
# Update package index and install the Microsoft package repository
|
||||||
sudo rpm -Uvh https://packages.microsoft.com/config/centos/8/packages-microsoft-prod.rpm
|
# sudo rpm -Uvh https://packages.microsoft.com/config/centos/8/packages-microsoft-prod.rpm
|
||||||
sudo dnf install -y dotnet-sdk-8.0
|
sudo dnf install -y dotnet-sdk-8.0
|
||||||
|
|
||||||
# Check if the service exists and stop it if it does
|
# Check if the service exists and stop it if it does
|
||||||
@ -33,12 +33,9 @@ if [[ "$1" != "$NO_NEW_KEY_FLAG" ]]; then
|
|||||||
jq --arg newApiKey "$NEW_API_KEY" '.Configuration.ApiKey = $newApiKey' $APPSETTINGS_FILE > tmp.$$.json && mv tmp.$$.json $APPSETTINGS_FILE
|
jq --arg newApiKey "$NEW_API_KEY" '.Configuration.ApiKey = $newApiKey' $APPSETTINGS_FILE > tmp.$$.json && mv tmp.$$.json $APPSETTINGS_FILE
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd
|
|
||||||
|
|
||||||
# Build and publish the .NET application
|
# Build and publish the .NET application
|
||||||
cd "$(dirname "$(realpath "$0")")/Agent"
|
sudo dotnet build Agent.csproj --configuration Release
|
||||||
sudo dotnet build --configuration Release
|
sudo dotnet publish Agent.csproj -c Release -o $INSTALL_DIR
|
||||||
sudo dotnet publish -c Release -o $INSTALL_DIR
|
|
||||||
|
|
||||||
# Create the systemd service unit file
|
# Create the systemd service unit file
|
||||||
sudo bash -c "cat > $SERVICE_FILE <<EOL
|
sudo bash -c "cat > $SERVICE_FILE <<EOL
|
||||||
@ -25,7 +25,9 @@ const GetApiRoute = (route: ApiRoutes, ...args: string[]): string => {
|
|||||||
args.forEach((arg) => {
|
args.forEach((arg) => {
|
||||||
result = result.replace(/{.*?}/, arg)
|
result = result.replace(/{.*?}/, arg)
|
||||||
})
|
})
|
||||||
|
// TODO: need env var
|
||||||
return `http://localhost:8080/${result}`
|
return `http://localhost:8080/${result}`
|
||||||
|
//return `http://websrv0001.corp.maks-it.com:8080/${result}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export { GetApiRoute, ApiRoutes }
|
export { GetApiRoute, ApiRoutes }
|
||||||
|
|||||||
@ -1,11 +1,19 @@
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
using MaksIT.LetsEncrypt.Services;
|
using MaksIT.LetsEncrypt.Services;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
namespace MaksIT.LetsEncrypt.Extensions;
|
namespace MaksIT.LetsEncrypt.Extensions;
|
||||||
public static class ServiceCollectionExtensions {
|
public static class ServiceCollectionExtensions {
|
||||||
public static void RegisterLetsEncrypt(this IServiceCollection services) {
|
public static void RegisterLetsEncrypt(this IServiceCollection services, ILetsEncryptConfiguration appSettings) {
|
||||||
|
|
||||||
|
|
||||||
|
var config = new LetsEncryptConfiguration {
|
||||||
|
Staging = appSettings.Staging,
|
||||||
|
Production = appSettings.Production
|
||||||
|
};
|
||||||
|
|
||||||
|
services.AddSingleton(config);
|
||||||
services.AddHttpClient<ILetsEncryptService, LetsEncryptService>();
|
services.AddHttpClient<ILetsEncryptService, LetsEncryptService>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
22
src/LetsEncrypt/LetsEncryptConfiguration.cs
Normal file
22
src/LetsEncrypt/LetsEncryptConfiguration.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MaksIT.LetsEncrypt {
|
||||||
|
|
||||||
|
|
||||||
|
public interface ILetsEncryptConfiguration {
|
||||||
|
string Production { get; set; }
|
||||||
|
string Staging { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class LetsEncryptConfiguration : ILetsEncryptConfiguration {
|
||||||
|
public required string Production { get; set; }
|
||||||
|
public required string Staging { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -22,6 +22,7 @@ using MaksIT.LetsEncrypt.Models.Interfaces;
|
|||||||
using MaksIT.LetsEncrypt.Models.Requests;
|
using MaksIT.LetsEncrypt.Models.Requests;
|
||||||
using MaksIT.LetsEncrypt.Entities.Jws;
|
using MaksIT.LetsEncrypt.Entities.Jws;
|
||||||
using MaksIT.LetsEncrypt.Entities.LetsEncrypt;
|
using MaksIT.LetsEncrypt.Entities.LetsEncrypt;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace MaksIT.LetsEncrypt.Services;
|
namespace MaksIT.LetsEncrypt.Services;
|
||||||
|
|
||||||
@ -39,14 +40,18 @@ public interface ILetsEncryptService {
|
|||||||
|
|
||||||
public class LetsEncryptService : ILetsEncryptService {
|
public class LetsEncryptService : ILetsEncryptService {
|
||||||
private readonly ILogger<LetsEncryptService> _logger;
|
private readonly ILogger<LetsEncryptService> _logger;
|
||||||
|
private readonly LetsEncryptConfiguration _appSettings;
|
||||||
private readonly HttpClient _httpClient;
|
private readonly HttpClient _httpClient;
|
||||||
private readonly IMemoryCache _memoryCache;
|
private readonly IMemoryCache _memoryCache;
|
||||||
|
|
||||||
public LetsEncryptService(
|
public LetsEncryptService(
|
||||||
ILogger<LetsEncryptService> logger,
|
ILogger<LetsEncryptService> logger,
|
||||||
|
LetsEncryptConfiguration appSettings,
|
||||||
HttpClient httpClient,
|
HttpClient httpClient,
|
||||||
IMemoryCache cache) {
|
IMemoryCache cache
|
||||||
|
) {
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_appSettings = appSettings;
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
_memoryCache = cache;
|
_memoryCache = cache;
|
||||||
}
|
}
|
||||||
@ -66,9 +71,7 @@ public class LetsEncryptService : ILetsEncryptService {
|
|||||||
|
|
||||||
state.IsStaging = isStaging;
|
state.IsStaging = isStaging;
|
||||||
// TODO: need to propagate from Configuration
|
// TODO: need to propagate from Configuration
|
||||||
_httpClient.BaseAddress ??= new Uri(isStaging
|
_httpClient.BaseAddress ??= new Uri(isStaging ? _appSettings.Staging : _appSettings.Production);
|
||||||
? "https://acme-staging-v02.api.letsencrypt.org/directory"
|
|
||||||
: "https://acme-v02.api.letsencrypt.org/directory");
|
|
||||||
|
|
||||||
if (state.Directory == null) {
|
if (state.Directory == null) {
|
||||||
var request = new HttpRequestMessage(HttpMethod.Get, new Uri("directory", UriKind.Relative));
|
var request = new HttpRequestMessage(HttpMethod.Get, new Uri("directory", UriKind.Relative));
|
||||||
|
|||||||
@ -1,16 +1,85 @@
|
|||||||
namespace MaksIT.LetsEncryptServer {
|
using MaksIT.LetsEncrypt;
|
||||||
|
|
||||||
|
namespace MaksIT.LetsEncryptServer {
|
||||||
|
|
||||||
public class Agent {
|
public class Agent {
|
||||||
public required string AgentHostname { get; set; }
|
|
||||||
public required int AgentPort { get; set; }
|
|
||||||
public required string AgentKey { get; set; }
|
|
||||||
|
|
||||||
public required string ServiceToReload { get; set; }
|
private string? _agentHostname;
|
||||||
|
public string AgentHostname {
|
||||||
|
get {
|
||||||
|
var env = Environment.GetEnvironmentVariable("MAKS-IT_AGENT_HOSTNAME");
|
||||||
|
return env ?? _agentHostname ?? string.Empty;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
_agentHostname = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int? _agentPort;
|
||||||
|
public int AgentPort {
|
||||||
|
get {
|
||||||
|
var env = Environment.GetEnvironmentVariable("MAKS-IT_AGENT_PORT");
|
||||||
|
return env != null ? int.Parse(env) : _agentPort ?? 0;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
_agentPort = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private string? _agentKey;
|
||||||
|
public string AgentKey {
|
||||||
|
get {
|
||||||
|
var env = Environment.GetEnvironmentVariable("MAKS-IT_AGENT_KEY");
|
||||||
|
return env ?? _agentKey ?? string.Empty;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
_agentKey = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string? _serviceToReload;
|
||||||
|
public string ServiceToReload {
|
||||||
|
get {
|
||||||
|
var env = Environment.GetEnvironmentVariable("MAKS-IT_AGENT_SERVICE");
|
||||||
|
return env ?? _serviceToReload ?? string.Empty;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
_serviceToReload = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Configuration {
|
|
||||||
public required string Production { get; set; }
|
|
||||||
public required string Staging { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
|
public class Configuration : ILetsEncryptConfiguration {
|
||||||
|
|
||||||
|
private string? _production;
|
||||||
|
public string Production {
|
||||||
|
get {
|
||||||
|
var env = Environment.GetEnvironmentVariable("LETSENCRYPT_SERVER_PRODUCTION");
|
||||||
|
return env ?? _production ?? string.Empty;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
_production = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private string? _staging;
|
||||||
|
public string Staging {
|
||||||
|
get {
|
||||||
|
var env = Environment.GetEnvironmentVariable("LETSENCRYPT_SERVER_STAGING");
|
||||||
|
return env ?? _staging ?? string.Empty;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
_staging = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public required Agent Agent { get; set; }
|
public required Agent Agent { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
|
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
|
||||||
USER app
|
USER app
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
EXPOSE 8080
|
EXPOSE 5000
|
||||||
|
|
||||||
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
||||||
ARG BUILD_CONFIGURATION=Release
|
ARG BUILD_CONFIGURATION=Release
|
||||||
|
|||||||
@ -3,6 +3,7 @@ using MaksIT.LetsEncrypt.Services;
|
|||||||
using MaksIT.LetsEncryptServer.Services;
|
using MaksIT.LetsEncryptServer.Services;
|
||||||
using MaksIT.LetsEncryptServer.BackgroundServices;
|
using MaksIT.LetsEncryptServer.BackgroundServices;
|
||||||
using MaksIT.LetsEncryptServer.Middlewares;
|
using MaksIT.LetsEncryptServer.Middlewares;
|
||||||
|
using MaksIT.LetsEncrypt.Extensions;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
@ -28,7 +29,8 @@ builder.Services.AddCors();
|
|||||||
|
|
||||||
builder.Services.AddMemoryCache();
|
builder.Services.AddMemoryCache();
|
||||||
|
|
||||||
builder.Services.AddHttpClient<ILetsEncryptService, LetsEncryptService>();
|
builder.Services.RegisterLetsEncrypt(appSettings);
|
||||||
|
|
||||||
builder.Services.AddSingleton<ICacheService, CacheService>();
|
builder.Services.AddSingleton<ICacheService, CacheService>();
|
||||||
builder.Services.AddSingleton<ICertsFlowService, CertsFlowService>();
|
builder.Services.AddSingleton<ICertsFlowService, CertsFlowService>();
|
||||||
builder.Services.AddSingleton<IAccountService, AccountService>();
|
builder.Services.AddSingleton<IAccountService, AccountService>();
|
||||||
|
|||||||
@ -12,8 +12,8 @@
|
|||||||
"Staging": "https://acme-staging-v02.api.letsencrypt.org/directory",
|
"Staging": "https://acme-staging-v02.api.letsencrypt.org/directory",
|
||||||
|
|
||||||
"Agent": {
|
"Agent": {
|
||||||
"AgentHostname": "http://lblsrv0001.corp.maks-it.com",
|
"AgentHostname": "http://websrv0001.corp.maks-it.com",
|
||||||
"AgentPort": 5000,
|
"AgentPort": 9000,
|
||||||
"AgentKey": "UGnCaElLLJClHgUeet/yr7vNvPf13b1WkDJQMfsiP6I=",
|
"AgentKey": "UGnCaElLLJClHgUeet/yr7vNvPf13b1WkDJQMfsiP6I=",
|
||||||
|
|
||||||
"ServiceToReload": "haproxy"
|
"ServiceToReload": "haproxy"
|
||||||
|
|||||||
@ -5,39 +5,39 @@
|
|||||||
"Match": {
|
"Match": {
|
||||||
"Path": "/.well-known/acme-challenge/{**catch-all}"
|
"Path": "/.well-known/acme-challenge/{**catch-all}"
|
||||||
},
|
},
|
||||||
"ClusterId": "letsencryptserver"
|
"ClusterId": "letsencrypt-server"
|
||||||
},
|
},
|
||||||
"swagger-route": {
|
"swagger-route": {
|
||||||
"Match": {
|
"Match": {
|
||||||
"Path": "/swagger/{**catch-all}"
|
"Path": "/swagger/{**catch-all}"
|
||||||
},
|
},
|
||||||
"ClusterId": "letsencryptserver"
|
"ClusterId": "letsencrypt-server"
|
||||||
},
|
},
|
||||||
"api-route": {
|
"api-route": {
|
||||||
"Match": {
|
"Match": {
|
||||||
"Path": "/api/{**catch-all}"
|
"Path": "/api/{**catch-all}"
|
||||||
},
|
},
|
||||||
"ClusterId": "letsencryptserver"
|
"ClusterId": "letsencrypt-server"
|
||||||
},
|
},
|
||||||
"default-route": {
|
"default-route": {
|
||||||
"Match": {
|
"Match": {
|
||||||
"Path": "{**catch-all}"
|
"Path": "{**catch-all}"
|
||||||
},
|
},
|
||||||
"ClusterId": "letsencryptapp"
|
"ClusterId": "letsencrypt-app"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Clusters": {
|
"Clusters": {
|
||||||
"letsencryptserver": {
|
"letsencrypt-server": {
|
||||||
"Destinations": {
|
"Destinations": {
|
||||||
"destination1": {
|
"destination1": {
|
||||||
"Address": "http://letsencryptserver:5000/"
|
"Address": "http://letsencrypt-server:5000/"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"letsencryptapp": {
|
"letsencrypt-app": {
|
||||||
"Destinations": {
|
"Destinations": {
|
||||||
"destination1": {
|
"destination1": {
|
||||||
"Address": "http://letsencryptapp:3000/"
|
"Address": "http://letsencrypt-app:3000/"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
46
src/docker-compose.final.yml
Normal file
46
src/docker-compose.final.yml
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
services:
|
||||||
|
letsencrypt-app:
|
||||||
|
image: ${DOCKER_REGISTRY-}letsencrypt-app
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ClientApp/Dockerfile
|
||||||
|
container_name: letsencrypt-app
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Production
|
||||||
|
- LETSENCRYPT_SERVER=http://websrv0001.corp.maks-it.com
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
network_mode: "host"
|
||||||
|
|
||||||
|
|
||||||
|
letsencrypt-server:
|
||||||
|
image: ${DOCKER_REGISTRY-}letsencrypt-server
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: LetsEncryptServer/Dockerfile
|
||||||
|
container_name: letsencrypt-server
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Production
|
||||||
|
- ASPNETCORE_HTTP_PORTS=9000
|
||||||
|
- LETSENCRYPT_SERVER_PRODUCTION=https://acme-v02.api.letsencrypt.org/directory
|
||||||
|
- LETSENCRYPT_SERVER_STAGING=https://acme-staging-v02.api.letsencrypt.org/directory
|
||||||
|
- MAKS_IT_AGENT_HOSTNAME=http://websrv0001.corp.maks-it.com
|
||||||
|
- MAKS-IT_AGENT_PORT=5000
|
||||||
|
- MAKS-IT_AGENT_KEY=UGnCaElLLJClHgUeet/yr7vNvPf13b1WkDJQMfsiP6I=
|
||||||
|
- MAKS-IT_AGENT_SERVICE=haproxy
|
||||||
|
volumes:
|
||||||
|
- ./docker-compose/LetsEncryptServer/acme:/app/acme
|
||||||
|
- ./docker-compose/LetsEncryptServer/cache:/app/cache
|
||||||
|
ports:
|
||||||
|
- "9000:9000"
|
||||||
|
network_mode: "host"
|
||||||
|
|
||||||
|
|
||||||
|
curl-test:
|
||||||
|
image: curlimages/curl:latest
|
||||||
|
container_name: curl-test
|
||||||
|
command: >
|
||||||
|
curl --location http://websrv0001.corp.maks-it.com:5000/HelloWorld
|
||||||
|
--header "x-api-key: UGnCaElLLJClHgUeet/yr7vNvPf13b1WkDJQMfsiP6I="
|
||||||
|
restart: "no"
|
||||||
|
network_mode: "host"
|
||||||
@ -1,24 +1,43 @@
|
|||||||
version: '3.9'
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
reverseProxy:
|
reverse-proxy:
|
||||||
|
container_name: reverse-proxy
|
||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
depends_on:
|
depends_on:
|
||||||
- letsencryptapp
|
- letsencrypt-app
|
||||||
- letsencryptserver
|
- letsencrypt-server
|
||||||
|
networks:
|
||||||
|
- maks-it
|
||||||
|
|
||||||
# letsencryptapp:
|
letsencrypt-app:
|
||||||
|
container_name: letsencrypt-app
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
|
- LETSENCRYPT_SERVER=http://localhost:8080
|
||||||
# ports:
|
# ports:
|
||||||
# - "3000:3000"
|
# - "3000:3000"
|
||||||
|
networks:
|
||||||
|
- maks-it
|
||||||
|
|
||||||
letsencryptserver:
|
letsencrypt-server:
|
||||||
|
container_name: letsencrypt-server
|
||||||
environment:
|
environment:
|
||||||
- ASPNETCORE_ENVIRONMENT=Development
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
- ASPNETCORE_HTTP_PORTS=5000
|
- ASPNETCORE_HTTP_PORTS=5000
|
||||||
|
- LETSENCRYPT_SERVER_PRODUCTION=https://acme-v02.api.letsencrypt.org/directory
|
||||||
|
- LETSENCRYPT_SERVER_STAGING=https://acme-staging-v02.api.letsencrypt.org/directory
|
||||||
|
- MAKS_IT_AGENT_HOSTNAME=http://websrv0001.corp.maks-it.com
|
||||||
|
- MAKS-IT_AGENT_PORT=5000
|
||||||
|
- MAKS-IT_AGENT_KEY=UGnCaElLLJClHgUeet/yr7vNvPf13b1WkDJQMfsiP6I=
|
||||||
|
- MAKS-IT_AGENT_SERVICE=haproxy
|
||||||
volumes:
|
volumes:
|
||||||
- ./docker-compose/LetsEncryptServer/acme:/app/bin/Debug/net8.0/acme
|
- ./docker-compose/LetsEncryptServer/acme:/app/bin/Debug/net8.0/acme
|
||||||
- ./docker-compose/LetsEncryptServer/cache:/app/bin/Debug/net8.0/cache
|
- ./docker-compose/LetsEncryptServer/cache:/app/bin/Debug/net8.0/cache
|
||||||
ports:
|
ports:
|
||||||
- "5000:5000"
|
- "5000:5000"
|
||||||
|
networks:
|
||||||
|
- maks-it
|
||||||
|
|
||||||
|
networks:
|
||||||
|
maks-it:
|
||||||
|
driver: bridge
|
||||||
@ -1,20 +1,18 @@
|
|||||||
version: '3.9'
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
letsencryptapp:
|
letsencrypt-app:
|
||||||
image: ${DOCKER_REGISTRY-}letsencryptapp
|
image: ${DOCKER_REGISTRY-}letsencrypt-app
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: ClientApp/Dockerfile
|
dockerfile: ClientApp/Dockerfile
|
||||||
|
|
||||||
reverseProxy:
|
reverse-proxy:
|
||||||
image: ${DOCKER_REGISTRY-}reverseproxy
|
image: ${DOCKER_REGISTRY-}reverse-proxy
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: ReverseProxy/Dockerfile
|
dockerfile: ReverseProxy/Dockerfile
|
||||||
|
|
||||||
letsencryptserver:
|
letsencrypt-server:
|
||||||
image: ${DOCKER_REGISTRY-}letsencryptserver
|
image: ${DOCKER_REGISTRY-}letsencrypt-server
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: LetsEncryptServer/Dockerfile
|
dockerfile: LetsEncryptServer/Dockerfile
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user