feat: ssl certificate sets custom ssl for applications
This commit is contained in:
@@ -0,0 +1,23 @@
|
|||||||
|
-- RedefineTables
|
||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
CREATE TABLE "new_ApplicationSettings" (
|
||||||
|
"id" TEXT NOT NULL PRIMARY KEY,
|
||||||
|
"applicationId" TEXT NOT NULL,
|
||||||
|
"dualCerts" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"debug" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"previews" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"autodeploy" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"isBot" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"isPublicRepository" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"isDBBranching" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"isCustomSSL" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" DATETIME NOT NULL,
|
||||||
|
CONSTRAINT "ApplicationSettings_applicationId_fkey" FOREIGN KEY ("applicationId") REFERENCES "Application" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
||||||
|
);
|
||||||
|
INSERT INTO "new_ApplicationSettings" ("applicationId", "autodeploy", "createdAt", "debug", "dualCerts", "id", "isBot", "isDBBranching", "isPublicRepository", "previews", "updatedAt") SELECT "applicationId", "autodeploy", "createdAt", "debug", "dualCerts", "id", "isBot", "isDBBranching", "isPublicRepository", "previews", "updatedAt" FROM "ApplicationSettings";
|
||||||
|
DROP TABLE "ApplicationSettings";
|
||||||
|
ALTER TABLE "new_ApplicationSettings" RENAME TO "ApplicationSettings";
|
||||||
|
CREATE UNIQUE INDEX "ApplicationSettings_applicationId_key" ON "ApplicationSettings"("applicationId");
|
||||||
|
PRAGMA foreign_key_check;
|
||||||
|
PRAGMA foreign_keys=ON;
|
@@ -172,6 +172,7 @@ model ApplicationSettings {
|
|||||||
isBot Boolean @default(false)
|
isBot Boolean @default(false)
|
||||||
isPublicRepository Boolean @default(false)
|
isPublicRepository Boolean @default(false)
|
||||||
isDBBranching Boolean @default(false)
|
isDBBranching Boolean @default(false)
|
||||||
|
isCustomSSL Boolean @default(false)
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
application Application @relation(fields: [applicationId], references: [id])
|
application Application @relation(fields: [applicationId], references: [id])
|
||||||
|
@@ -60,40 +60,49 @@ async function copySSLCertificates() {
|
|||||||
const destinations = await prisma.destinationDocker.findMany({ where: { isCoolifyProxyUsed: true, teams: { some: { id: { in: [...teamIds] } } } } })
|
const destinations = await prisma.destinationDocker.findMany({ where: { isCoolifyProxyUsed: true, teams: { some: { id: { in: [...teamIds] } } } } })
|
||||||
for (const destination of destinations) {
|
for (const destination of destinations) {
|
||||||
if (destination.remoteEngine) {
|
if (destination.remoteEngine) {
|
||||||
|
|
||||||
const { id: dockerId, remoteIpAddress, remoteVerified } = destination
|
const { id: dockerId, remoteIpAddress, remoteVerified } = destination
|
||||||
if (!remoteVerified) {
|
if (!remoteVerified) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// TODO: copy certificates to remote engine
|
|
||||||
for (const certificate of certificates) {
|
for (const certificate of certificates) {
|
||||||
const { id, key, cert } = certificate
|
try {
|
||||||
const decryptedKey = decrypt(key)
|
const { id, key, cert } = certificate
|
||||||
await fs.writeFile(`/tmp/${id}-key.pem`, decryptedKey)
|
const decryptedKey = decrypt(key)
|
||||||
await fs.writeFile(`/tmp/${id}-cert.pem`, cert)
|
await fs.writeFile(`/tmp/${id}-key.pem`, decryptedKey)
|
||||||
await asyncExecShell(`scp /tmp/${id}-cert.pem /tmp/${id}-key.pem ${remoteIpAddress}:/tmp/`)
|
await fs.writeFile(`/tmp/${id}-cert.pem`, cert)
|
||||||
await fs.rm(`/tmp/${id}-key.pem`)
|
await asyncExecShell(`scp /tmp/${id}-cert.pem /tmp/${id}-key.pem ${remoteIpAddress}:/tmp/`)
|
||||||
await fs.rm(`/tmp/${id}-cert.pem`)
|
await fs.rm(`/tmp/${id}-key.pem`)
|
||||||
await executeSSHCmd({ dockerId, command: `docker exec coolify-proxy sh -c 'test -d /etc/traefik/acme/custom/ || mkdir -p /etc/traefik/acme/custom/'` })
|
await fs.rm(`/tmp/${id}-cert.pem`)
|
||||||
await executeSSHCmd({ dockerId, command: `docker cp /tmp/${id}-key.pem coolify-proxy:/etc/traefik/acme/custom/ && rm /tmp/${id}-key.pem` })
|
await executeSSHCmd({ dockerId, command: `docker exec coolify-proxy sh -c 'test -d /etc/traefik/acme/custom/ || mkdir -p /etc/traefik/acme/custom/'` })
|
||||||
await executeSSHCmd({ dockerId, command: `docker cp /tmp/${id}-cert.pem coolify-proxy:/etc/traefik/acme/custom/ && rm /tmp/${id}-cert.pem` })
|
await executeSSHCmd({ dockerId, command: `docker cp /tmp/${id}-key.pem coolify-proxy:/etc/traefik/acme/custom/ && rm /tmp/${id}-key.pem` })
|
||||||
|
await executeSSHCmd({ dockerId, command: `docker cp /tmp/${id}-cert.pem coolify-proxy:/etc/traefik/acme/custom/ && rm /tmp/${id}-cert.pem` })
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Error copying SSL certificates to remote engine', error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
for (const certificate of certificates) {
|
for (const certificate of certificates) {
|
||||||
const { id, key, cert } = certificate
|
try {
|
||||||
const decryptedKey = decrypt(key)
|
const { id, key, cert } = certificate
|
||||||
await asyncExecShell(`docker exec coolify-proxy sh -c 'test -d /etc/traefik/acme/custom/ || mkdir -p /etc/traefik/acme/custom/'`)
|
const decryptedKey = decrypt(key)
|
||||||
await fs.writeFile(`/tmp/${id}-key.pem`, decryptedKey)
|
await asyncExecShell(`docker exec coolify-proxy sh -c 'test -d /etc/traefik/acme/custom/ || mkdir -p /etc/traefik/acme/custom/'`)
|
||||||
await fs.writeFile(`/tmp/${id}-cert.pem`, cert)
|
await fs.writeFile(`/tmp/${id}-key.pem`, decryptedKey)
|
||||||
await asyncExecShell(`docker cp /tmp/${id}-key.pem coolify-proxy:/etc/traefik/acme/custom/`)
|
await fs.writeFile(`/tmp/${id}-cert.pem`, cert)
|
||||||
await asyncExecShell(`docker cp /tmp/${id}-cert.pem coolify-proxy:/etc/traefik/acme/custom/`)
|
await asyncExecShell(`docker cp /tmp/${id}-key.pem coolify-proxy:/etc/traefik/acme/custom/`)
|
||||||
await fs.rm(`/tmp/${id}-key.pem`)
|
await asyncExecShell(`docker cp /tmp/${id}-cert.pem coolify-proxy:/etc/traefik/acme/custom/`)
|
||||||
await fs.rm(`/tmp/${id}-cert.pem`)
|
await fs.rm(`/tmp/${id}-key.pem`)
|
||||||
|
await fs.rm(`/tmp/${id}-cert.pem`)
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Error copying SSL certificates to remote engine', error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.log('Error copying SSL certificates', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function checkProxies() {
|
async function checkProxies() {
|
||||||
|
@@ -321,17 +321,12 @@ export async function saveApplication(request: FastifyRequest<SaveApplication>,
|
|||||||
export async function saveApplicationSettings(request: FastifyRequest<SaveApplicationSettings>, reply: FastifyReply) {
|
export async function saveApplicationSettings(request: FastifyRequest<SaveApplicationSettings>, reply: FastifyReply) {
|
||||||
try {
|
try {
|
||||||
const { id } = request.params
|
const { id } = request.params
|
||||||
const { debug, previews, dualCerts, autodeploy, branch, projectId, isBot, isDBBranching } = request.body
|
const { debug, previews, dualCerts, autodeploy, branch, projectId, isBot, isDBBranching, isCustomSSL } = request.body
|
||||||
// const isDouble = await checkDoubleBranch(branch, projectId);
|
|
||||||
// if (isDouble && autodeploy) {
|
|
||||||
// await prisma.applicationSettings.updateMany({ where: { application: { branch, projectId } }, data: { autodeploy: false } })
|
|
||||||
// throw { status: 500, message: 'Cannot activate automatic deployments until only one application is defined for this repository / branch.' }
|
|
||||||
// }
|
|
||||||
await prisma.application.update({
|
await prisma.application.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: { fqdn: isBot ? null : undefined, settings: { update: { debug, previews, dualCerts, autodeploy, isBot, isDBBranching } } },
|
data: { fqdn: isBot ? null : undefined, settings: { update: { debug, previews, dualCerts, autodeploy, isBot, isDBBranching, isCustomSSL } } },
|
||||||
include: { destinationDocker: true }
|
include: { destinationDocker: true }
|
||||||
});
|
});
|
||||||
return reply.code(201).send();
|
return reply.code(201).send();
|
||||||
} catch ({ status, message }) {
|
} catch ({ status, message }) {
|
||||||
return errorHandler({ status, message })
|
return errorHandler({ status, message })
|
||||||
|
@@ -26,7 +26,7 @@ export interface SaveApplication extends OnlyId {
|
|||||||
}
|
}
|
||||||
export interface SaveApplicationSettings extends OnlyId {
|
export interface SaveApplicationSettings extends OnlyId {
|
||||||
Querystring: { domain: string; };
|
Querystring: { domain: string; };
|
||||||
Body: { debug: boolean; previews: boolean; dualCerts: boolean; autodeploy: boolean; branch: string; projectId: number; isBot: boolean; isDBBranching: boolean };
|
Body: { debug: boolean; previews: boolean; dualCerts: boolean; autodeploy: boolean; branch: string; projectId: number; isBot: boolean; isDBBranching: boolean, isCustomSSL: boolean };
|
||||||
}
|
}
|
||||||
export interface DeleteApplication extends OnlyId {
|
export interface DeleteApplication extends OnlyId {
|
||||||
Querystring: { domain: string; };
|
Querystring: { domain: string; };
|
||||||
|
@@ -45,6 +45,7 @@ const root: FastifyPluginAsync = async (fastify): Promise<void> => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
await prisma.certificate.create({ data: { cert, key: encrypt(key), team: { connect: { id: teamId } } } })
|
await prisma.certificate.create({ data: { cert, key: encrypt(key), team: { connect: { id: teamId } } } })
|
||||||
|
await prisma.applicationSettings.updateMany({ where: { application: { AND: [{ fqdn: { endsWith: cn } }, { fqdn: { startsWith: 'https' } }] } }, data: { isCustomSSL: true } })
|
||||||
return { message: 'Certificated uploaded' }
|
return { message: 'Certificated uploaded' }
|
||||||
} catch ({ status, message }) {
|
} catch ({ status, message }) {
|
||||||
return errorHandler({ status, message });
|
return errorHandler({ status, message });
|
||||||
|
@@ -6,7 +6,7 @@ import { TraefikOtherConfiguration } from "./types";
|
|||||||
import { OnlyId } from "../../../types";
|
import { OnlyId } from "../../../types";
|
||||||
|
|
||||||
function configureMiddleware(
|
function configureMiddleware(
|
||||||
{ id, container, port, domain, nakedDomain, isHttps, isWWW, isDualCerts, scriptName, type },
|
{ id, container, port, domain, nakedDomain, isHttps, isWWW, isDualCerts, scriptName, type, isCustomSSL },
|
||||||
traefik
|
traefik
|
||||||
) {
|
) {
|
||||||
if (isHttps) {
|
if (isHttps) {
|
||||||
@@ -55,7 +55,7 @@ function configureMiddleware(
|
|||||||
entrypoints: ['websecure'],
|
entrypoints: ['websecure'],
|
||||||
rule: `(Host(\`${nakedDomain}\`) || Host(\`www.${nakedDomain}\`)) && PathPrefix(\`/\`)`,
|
rule: `(Host(\`${nakedDomain}\`) || Host(\`www.${nakedDomain}\`)) && PathPrefix(\`/\`)`,
|
||||||
service: `${id}`,
|
service: `${id}`,
|
||||||
tls: {
|
tls: isCustomSSL ? true : {
|
||||||
certresolver: 'letsencrypt'
|
certresolver: 'letsencrypt'
|
||||||
},
|
},
|
||||||
middlewares: []
|
middlewares: []
|
||||||
@@ -66,7 +66,7 @@ function configureMiddleware(
|
|||||||
entrypoints: ['websecure'],
|
entrypoints: ['websecure'],
|
||||||
rule: `Host(\`www.${nakedDomain}\`) && PathPrefix(\`/\`)`,
|
rule: `Host(\`www.${nakedDomain}\`) && PathPrefix(\`/\`)`,
|
||||||
service: `${id}`,
|
service: `${id}`,
|
||||||
tls: {
|
tls: isCustomSSL ? true : {
|
||||||
certresolver: 'letsencrypt'
|
certresolver: 'letsencrypt'
|
||||||
},
|
},
|
||||||
middlewares: []
|
middlewares: []
|
||||||
@@ -99,7 +99,7 @@ function configureMiddleware(
|
|||||||
entrypoints: ['websecure'],
|
entrypoints: ['websecure'],
|
||||||
rule: `Host(\`${domain}\`) && PathPrefix(\`/\`)`,
|
rule: `Host(\`${domain}\`) && PathPrefix(\`/\`)`,
|
||||||
service: `${id}`,
|
service: `${id}`,
|
||||||
tls: {
|
tls: isCustomSSL ? true : {
|
||||||
certresolver: 'letsencrypt'
|
certresolver: 'letsencrypt'
|
||||||
},
|
},
|
||||||
middlewares: []
|
middlewares: []
|
||||||
@@ -179,7 +179,7 @@ function configureMiddleware(
|
|||||||
export async function traefikConfiguration(request, reply) {
|
export async function traefikConfiguration(request, reply) {
|
||||||
try {
|
try {
|
||||||
const sslpath = '/etc/traefik/acme/custom';
|
const sslpath = '/etc/traefik/acme/custom';
|
||||||
const certificates = await prisma.certificate.findMany()
|
const certificates = await prisma.certificate.findMany({ where: { team: { applications: { some: { settings: { isCustomSSL: true } } }, destinationDocker: { some: { remoteEngine: false, isCoolifyProxyUsed: true } } } } })
|
||||||
let parsedCertificates = []
|
let parsedCertificates = []
|
||||||
for (const certificate of certificates) {
|
for (const certificate of certificates) {
|
||||||
parsedCertificates.push({
|
parsedCertificates.push({
|
||||||
@@ -236,7 +236,7 @@ export async function traefikConfiguration(request, reply) {
|
|||||||
port,
|
port,
|
||||||
destinationDocker,
|
destinationDocker,
|
||||||
destinationDockerId,
|
destinationDockerId,
|
||||||
settings: { previews, dualCerts }
|
settings: { previews, dualCerts, isCustomSSL }
|
||||||
} = application;
|
} = application;
|
||||||
if (destinationDockerId) {
|
if (destinationDockerId) {
|
||||||
const { network, id: dockerId } = destinationDocker;
|
const { network, id: dockerId } = destinationDocker;
|
||||||
@@ -256,7 +256,8 @@ export async function traefikConfiguration(request, reply) {
|
|||||||
isRunning,
|
isRunning,
|
||||||
isHttps,
|
isHttps,
|
||||||
isWWW,
|
isWWW,
|
||||||
isDualCerts: dualCerts
|
isDualCerts: dualCerts,
|
||||||
|
isCustomSSL
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (previews) {
|
if (previews) {
|
||||||
@@ -279,7 +280,8 @@ export async function traefikConfiguration(request, reply) {
|
|||||||
nakedDomain,
|
nakedDomain,
|
||||||
isHttps,
|
isHttps,
|
||||||
isWWW,
|
isWWW,
|
||||||
isDualCerts: dualCerts
|
isDualCerts: dualCerts,
|
||||||
|
isCustomSSL
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -547,7 +549,7 @@ export async function remoteTraefikConfiguration(request: FastifyRequest<OnlyId>
|
|||||||
const { id } = request.params
|
const { id } = request.params
|
||||||
try {
|
try {
|
||||||
const sslpath = '/etc/traefik/acme/custom';
|
const sslpath = '/etc/traefik/acme/custom';
|
||||||
const certificates = await prisma.certificate.findMany({ where: { team: { destinationDocker: { some: { id, remoteEngine: true, isCoolifyProxyUsed: true, remoteVerified: true } } } } })
|
const certificates = await prisma.certificate.findMany({ where: { team: { applications: { some: { settings: { isCustomSSL: true } } }, destinationDocker: { some: { id, remoteEngine: true, isCoolifyProxyUsed: true, remoteVerified: true } } } } })
|
||||||
let parsedCertificates = []
|
let parsedCertificates = []
|
||||||
for (const certificate of certificates) {
|
for (const certificate of certificates) {
|
||||||
parsedCertificates.push({
|
parsedCertificates.push({
|
||||||
|
@@ -132,7 +132,7 @@
|
|||||||
<ellipse cx="12" cy="6" rx="8" ry="3" />
|
<ellipse cx="12" cy="6" rx="8" ry="3" />
|
||||||
<path d="M4 6v6a8 3 0 0 0 16 0v-6" />
|
<path d="M4 6v6a8 3 0 0 0 16 0v-6" />
|
||||||
<path d="M4 12v6a8 3 0 0 0 16 0v-6" />
|
<path d="M4 12v6a8 3 0 0 0 16 0v-6" />
|
||||||
</svg>Peristent Volumes</a
|
</svg>Persistent Volumes</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
|
@@ -61,12 +61,14 @@
|
|||||||
let debug = application.settings.debug;
|
let debug = application.settings.debug;
|
||||||
let previews = application.settings.previews;
|
let previews = application.settings.previews;
|
||||||
let dualCerts = application.settings.dualCerts;
|
let dualCerts = application.settings.dualCerts;
|
||||||
|
let isCustomSSL = application.settings.isCustomSSL;
|
||||||
let autodeploy = application.settings.autodeploy;
|
let autodeploy = application.settings.autodeploy;
|
||||||
let isBot = application.settings.isBot;
|
let isBot = application.settings.isBot;
|
||||||
let isDBBranching = application.settings.isDBBranching;
|
let isDBBranching = application.settings.isDBBranching;
|
||||||
|
|
||||||
let baseDatabaseBranch: any = application?.connectedDatabase?.hostedDatabaseDBName || null;
|
let baseDatabaseBranch: any = application?.connectedDatabase?.hostedDatabaseDBName || null;
|
||||||
let nonWWWDomain = application.fqdn && getDomain(application.fqdn).replace(/^www\./, '');
|
let nonWWWDomain = application.fqdn && getDomain(application.fqdn).replace(/^www\./, '');
|
||||||
|
let isHttps = application.fqdn && application.fqdn.startsWith('https://');
|
||||||
let isNonWWWDomainOK = false;
|
let isNonWWWDomainOK = false;
|
||||||
let isWWWDomainOK = false;
|
let isWWWDomainOK = false;
|
||||||
|
|
||||||
@@ -92,7 +94,7 @@
|
|||||||
if (window.location.hostname === 'demo.coolify.io' && !application.fqdn) {
|
if (window.location.hostname === 'demo.coolify.io' && !application.fqdn) {
|
||||||
application.fqdn = `http://${cuid()}.demo.coolify.io`;
|
application.fqdn = `http://${cuid()}.demo.coolify.io`;
|
||||||
await handleSubmit();
|
await handleSubmit();
|
||||||
}
|
}
|
||||||
await getBaseBuildImages();
|
await getBaseBuildImages();
|
||||||
});
|
});
|
||||||
async function getBaseBuildImages() {
|
async function getBaseBuildImages() {
|
||||||
@@ -141,6 +143,9 @@
|
|||||||
if (name === 'autodeploy') {
|
if (name === 'autodeploy') {
|
||||||
autodeploy = !autodeploy;
|
autodeploy = !autodeploy;
|
||||||
}
|
}
|
||||||
|
if (name === 'isCustomSSL') {
|
||||||
|
isCustomSSL = !isCustomSSL;
|
||||||
|
}
|
||||||
if (name === 'isBot') {
|
if (name === 'isBot') {
|
||||||
if ($status.application.isRunning) return;
|
if ($status.application.isRunning) return;
|
||||||
isBot = !isBot;
|
isBot = !isBot;
|
||||||
@@ -159,6 +164,7 @@
|
|||||||
isBot,
|
isBot,
|
||||||
autodeploy,
|
autodeploy,
|
||||||
isDBBranching,
|
isDBBranching,
|
||||||
|
isCustomSSL,
|
||||||
branch: application.branch,
|
branch: application.branch,
|
||||||
projectId: application.projectId
|
projectId: application.projectId
|
||||||
});
|
});
|
||||||
@@ -185,6 +191,9 @@
|
|||||||
if (name === 'isDBBranching') {
|
if (name === 'isDBBranching') {
|
||||||
isDBBranching = !isDBBranching;
|
isDBBranching = !isDBBranching;
|
||||||
}
|
}
|
||||||
|
if (name === 'isCustomSSL') {
|
||||||
|
isCustomSSL = !isCustomSSL;
|
||||||
|
}
|
||||||
return errorNotification(error);
|
return errorNotification(error);
|
||||||
} finally {
|
} finally {
|
||||||
$isDeploymentEnabled = checkIfDeploymentEnabledApplications($appSession.isAdmin, application);
|
$isDeploymentEnabled = checkIfDeploymentEnabledApplications($appSession.isAdmin, application);
|
||||||
@@ -214,6 +223,11 @@
|
|||||||
message: 'Configuration saved.',
|
message: 'Configuration saved.',
|
||||||
type: 'success'
|
type: 'success'
|
||||||
});
|
});
|
||||||
|
if (application.fqdn && application.fqdn.startsWith('https')) {
|
||||||
|
isHttps = true;
|
||||||
|
} else {
|
||||||
|
isHttps = false;
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
if (error?.message.startsWith($t('application.dns_not_set_partial_error'))) {
|
if (error?.message.startsWith($t('application.dns_not_set_partial_error'))) {
|
||||||
@@ -548,6 +562,18 @@
|
|||||||
on:click={() => !$status.application.isRunning && changeSettings('dualCerts')}
|
on:click={() => !$status.application.isRunning && changeSettings('dualCerts')}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{#if isHttps}
|
||||||
|
<div class="grid grid-cols-2 items-center pb-4">
|
||||||
|
<Setting
|
||||||
|
id="isCustomSSL"
|
||||||
|
isCenter={false}
|
||||||
|
bind:setting={isCustomSSL}
|
||||||
|
title="Use Custom SSL Certificate"
|
||||||
|
description="Use Custom SSL Certificated added in the Settings/SSL Certificates section. <br><br>By default, the SSL certificate is generated automatically through Let's Encrypt"
|
||||||
|
on:click={() => changeSettings('isCustomSSL')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
{#if application.buildPack === 'python'}
|
{#if application.buildPack === 'python'}
|
||||||
<div class="grid grid-cols-2 items-center">
|
<div class="grid grid-cols-2 items-center">
|
||||||
@@ -769,4 +795,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -41,7 +41,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function deleteCertificate(id: string) {
|
async function deleteCertificate(id: string) {
|
||||||
const sure = confirm('Are you sure you would like to delete this SSH key?');
|
const sure = confirm('Are you sure you would like to delete this SSL Certificate?');
|
||||||
if (sure) {
|
if (sure) {
|
||||||
try {
|
try {
|
||||||
if (!id) return;
|
if (!id) return;
|
||||||
@@ -89,7 +89,7 @@
|
|||||||
<div class="text-sm">No SSL Certificate found</div>
|
<div class="text-sm">No SSL Certificate found</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if isModalActive}
|
{#if isModalActive}
|
||||||
<input type="checkbox" id="my-modal" class="modal-toggle" />
|
<input type="checkbox" id="my-modal" class="modal-toggle" />
|
||||||
<div class="modal modal-bottom sm:modal-middle ">
|
<div class="modal modal-bottom sm:modal-middle ">
|
||||||
|
Reference in New Issue
Block a user