mirror of
https://github.com/koush/scrypted.git
synced 2026-02-03 14:13:28 +00:00
Revert "cloud: revert duckdns + letsencrypt"
This reverts commit 7d022548b9.
This commit is contained in:
1
plugins/cloud/.gitignore
vendored
1
plugins/cloud/.gitignore
vendored
@@ -2,3 +2,4 @@
|
||||
out/
|
||||
node_modules/
|
||||
dist/
|
||||
external
|
||||
|
||||
7776
plugins/cloud/package-lock.json
generated
7776
plugins/cloud/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -27,6 +27,7 @@
|
||||
"scrypted": {
|
||||
"name": "Scrypted Cloud",
|
||||
"type": "API",
|
||||
"realfs": true,
|
||||
"interfaces": [
|
||||
"SystemSettings",
|
||||
"BufferConverter",
|
||||
@@ -36,6 +37,12 @@
|
||||
"HttpRequestHandler"
|
||||
]
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@greenlock/manager": "^3.1.0",
|
||||
"@koush/greenlock": "^4.0.9",
|
||||
"acme-dns-01-duckdns": "^3.0.1",
|
||||
"greenlock-store-fs": "^3.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@eneris/push-receiver": "^3.1.4",
|
||||
"@scrypted/common": "file:../../common",
|
||||
@@ -50,5 +57,5 @@
|
||||
"@types/nat-upnp": "^1.1.2",
|
||||
"@types/node": "^20.4.5"
|
||||
},
|
||||
"version": "0.1.24"
|
||||
"version": "0.1.27"
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@ import { PushManager } from './push';
|
||||
import { readLine } from '../../../common/src/read-stream';
|
||||
import { qsparse, qsstringify } from "./qs";
|
||||
|
||||
|
||||
console.warn('webpack', require('@greenlock/manager'), require('greenlock-store-fs'), require('acme-dns-01-duckdns'));
|
||||
|
||||
const { deviceManager, endpointManager, systemManager } = sdk;
|
||||
|
||||
export const DEFAULT_SENDER_ID = '827888101440';
|
||||
@@ -34,9 +37,9 @@ class ScryptedPush extends ScryptedDeviceBase implements BufferConverter {
|
||||
}
|
||||
|
||||
async convert(data: Buffer | string, fromMimeType: string): Promise<Buffer> {
|
||||
if (this.cloud.storageSettings.values.forwardingMode === 'Custom Domain' && this.cloud.storageSettings.values.hostname) {
|
||||
return Buffer.from(`https://${this.cloud.getHostname()}${await this.cloud.getCloudMessagePath()}/${data}`);
|
||||
}
|
||||
const validDomain = this.cloud.getSSLHostname();
|
||||
if (validDomain)
|
||||
return Buffer.from(`https://${validDomain}${await this.cloud.getCloudMessagePath()}/${data}`);
|
||||
|
||||
const url = `http://127.0.0.1/push/${data}`;
|
||||
return this.cloud.whitelist(url, 10 * 365 * 24 * 60 * 60 * 1000, `https://${this.cloud.getHostname()}${SCRYPTED_CLOUD_MESSAGE_PATH}`);
|
||||
@@ -83,6 +86,26 @@ class ScryptedCloud extends ScryptedDeviceBase implements OauthClient, Settings,
|
||||
placeholder: 'my-server.dyndns.com',
|
||||
onPut: () => this.scheduleRefreshPortForward(),
|
||||
},
|
||||
duckDnsToken: {
|
||||
title: 'Duck DNS Token',
|
||||
placeholder: 'xxxxx123456',
|
||||
onPut: () => {
|
||||
this.storageSettings.values.duckDnsCertValid = false;
|
||||
this.log.a('Reload the Scrypted Cloud Plugin to apply the Duck DNS change.');
|
||||
}
|
||||
},
|
||||
duckDnsHostname: {
|
||||
title: 'Duck DNS Hostname',
|
||||
placeholder: 'my-scrypted.duckdns.org',
|
||||
onPut: () => {
|
||||
this.storageSettings.values.duckDnsCertValid = false;
|
||||
this.log.a('Reload the Scrypted Cloud Plugin to apply the Duck DNS change.');
|
||||
}
|
||||
},
|
||||
duckDnsCertValid: {
|
||||
type: 'boolean',
|
||||
hide: true,
|
||||
},
|
||||
securePort: {
|
||||
title: 'Local HTTPS Port',
|
||||
description: 'The Scrypted Cloud plugin listens on this port for for cloud connections. The router must use UPNP, port forwarding, or a reverse proxy to send requests to this port.',
|
||||
@@ -182,6 +205,20 @@ class ScryptedCloud extends ScryptedDeviceBase implements OauthClient, Settings,
|
||||
}
|
||||
};
|
||||
|
||||
this.storageSettings.settings.duckDnsToken.onGet = async () => {
|
||||
return {
|
||||
hide: this.storageSettings.values.forwardingMode === 'Custom Domain'
|
||||
|| this.storageSettings.values.forwardingMode === 'Disabled',
|
||||
}
|
||||
};
|
||||
|
||||
this.storageSettings.settings.duckDnsHostname.onGet = async () => {
|
||||
return {
|
||||
hide: this.storageSettings.values.forwardingMode === 'Custom Domain'
|
||||
|| this.storageSettings.values.forwardingMode === 'Disabled',
|
||||
}
|
||||
};
|
||||
|
||||
this.log.clearAlerts();
|
||||
|
||||
this.storageSettings.settings.securePort.onPut = (ov, nv) => {
|
||||
@@ -230,12 +267,96 @@ class ScryptedCloud extends ScryptedDeviceBase implements OauthClient, Settings,
|
||||
this.storageSettings.values.upnpPort = upnpPort;
|
||||
|
||||
// scrypted cloud will replace localhost with requesting ip.
|
||||
const ip = this.storageSettings.values.forwardingMode === 'Custom Domain'
|
||||
? this.storageSettings.values.hostname?.toString()
|
||||
: (await axios(`https://${SCRYPTED_SERVER}/_punch/ip`)).data.ip;
|
||||
let ip: string;
|
||||
if (this.storageSettings.values.forwardingMode === 'Custom Domain') {
|
||||
ip = this.storageSettings.values.hostname?.toString();
|
||||
if (!ip)
|
||||
throw new Error('Hostname is required for port Custom Domain setup.');
|
||||
}
|
||||
else if (this.storageSettings.values.duckDnsHostname && this.storageSettings.values.duckDnsToken) {
|
||||
try {
|
||||
const url = new URL('https://www.duckdns.org/update');
|
||||
url.searchParams.set('domains', this.storageSettings.values.duckDnsHostname);
|
||||
url.searchParams.set('token', this.storageSettings.values.duckDnsToken);
|
||||
await axios(url.toString());
|
||||
}
|
||||
catch (e) {
|
||||
this.console.error('Duck DNS Erorr', e);
|
||||
throw new Error('Duck DNS Error. See Console Logs.');
|
||||
}
|
||||
try {
|
||||
const pluginVolume = process.env.SCRYPTED_PLUGIN_VOLUME;
|
||||
const greenlockD = path.join(pluginVolume, 'greenlock.d');
|
||||
|
||||
if (!ip)
|
||||
throw new Error('Hostname is required for port Custom Domain setup.');
|
||||
// const dns01 = require('acme-dns-01-duckdns').create({
|
||||
// baseUrl: 'https://www.duckdns.org/update',
|
||||
// token: 'abcd',// this.storageSettings.values.duckDnsToken,
|
||||
// });
|
||||
// hack
|
||||
// dns01.module = 'acme-dns-01-duckdns';
|
||||
// dns01.token = this.storageSettings.values.duckDnsToken;
|
||||
|
||||
const Greenlock = require('@koush/greenlock');
|
||||
const greenlock = Greenlock.create({
|
||||
packageRoot: process.env.NODE_PATH,
|
||||
configDir: greenlockD,
|
||||
packageAgent: 'Scrypted/1.0',
|
||||
maintainerEmail: 'koushd@gmail.com',
|
||||
staging: true,
|
||||
notify: function (event, details) {
|
||||
if ('error' === event) {
|
||||
// `details` is an error object in this case
|
||||
console.error(details);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
await greenlock.manager
|
||||
.defaults({
|
||||
challenges: {
|
||||
'dns-01': {
|
||||
module: 'acme-dns-01-duckdns',
|
||||
token: this.storageSettings.values.duckDnsToken,
|
||||
},
|
||||
},
|
||||
agreeToTerms: true,
|
||||
subscriberEmail: 'koushd@gmail.com',
|
||||
});
|
||||
|
||||
const altnames = [this.storageSettings.values.duckDnsHostname];
|
||||
|
||||
const r = await greenlock
|
||||
.add({
|
||||
subject: altnames[0],
|
||||
altnames: altnames
|
||||
});
|
||||
|
||||
const result = await greenlock
|
||||
.get({ servername: this.storageSettings.values.duckDnsHostname });
|
||||
|
||||
|
||||
this.storageSettings.values.duckDnsCertValid = true;
|
||||
const { pems } = result;
|
||||
const certificate = this.storageSettings.values.certificate;
|
||||
if (certificate.certificate !== pems.cert || certificate.serviceKey !== pems.privkey) {
|
||||
certificate.certificate = pems.cert;
|
||||
certificate.serviceKey = pems.privkey;
|
||||
this.storageSettings.values.certificate = certificate;
|
||||
deviceManager.requestRestart();
|
||||
}
|
||||
|
||||
this.console.log(r);
|
||||
}
|
||||
catch (e) {
|
||||
this.console.error("Let's Encrypt Error", e);
|
||||
throw new Error("Let's Encrypt Error. See Console Logs.");
|
||||
}
|
||||
|
||||
ip = this.storageSettings.values.duckDnsHostname;
|
||||
}
|
||||
else {
|
||||
ip = (await axios(`https://${SCRYPTED_SERVER}/_punch/ip`)).data.ip;
|
||||
}
|
||||
|
||||
if (this.storageSettings.values.forwardingMode === 'Custom Domain')
|
||||
upnpPort = 443;
|
||||
@@ -344,7 +465,7 @@ class ScryptedCloud extends ScryptedDeviceBase implements OauthClient, Settings,
|
||||
async whitelist(localUrl: string, ttl: number, baseUrl: string): Promise<Buffer> {
|
||||
const local = new URL(localUrl);
|
||||
|
||||
if (this.storageSettings.values.forwardingMode === 'Custom Domain' && this.storageSettings.values.hostname) {
|
||||
if (this.getSSLHostname()) {
|
||||
return Buffer.from(`${baseUrl}${local.pathname}`);
|
||||
}
|
||||
|
||||
@@ -394,7 +515,9 @@ class ScryptedCloud extends ScryptedDeviceBase implements OauthClient, Settings,
|
||||
|
||||
getAuthority() {
|
||||
const upnp_port = this.storageSettings.values.forwardingMode === 'Custom Domain' ? 443 : this.storageSettings.values.upnpPort;
|
||||
const hostname = this.storageSettings.values.forwardingMode === 'Custom Domain' ? this.storageSettings.values.hostname : undefined;
|
||||
const hostname = this.storageSettings.values.forwardingMode === 'Custom Domain'
|
||||
? this.storageSettings.values.hostname
|
||||
: this.storageSettings.values.duckDnsToken && this.storageSettings.values.duckDnsHostname;
|
||||
|
||||
if (upnp_port === 443 && !hostname) {
|
||||
const error = this.storageSettings.values.forwardingMode === 'Custom Domain'
|
||||
@@ -480,10 +603,14 @@ class ScryptedCloud extends ScryptedDeviceBase implements OauthClient, Settings,
|
||||
async releaseDevice(id: string, nativeId: string): Promise<void> {
|
||||
}
|
||||
|
||||
getSSLHostname() {
|
||||
const validDomain = (this.storageSettings.values.forwardingMode === 'Custom Domain' && this.storageSettings.values.hostname)
|
||||
|| (this.storageSettings.values.duckDnsCertValid && this.storageSettings.values.duckDnsHostname && this.storageSettings.values.upnpPort && `${this.storageSettings.values.duckDnsHostname}:${this.storageSettings.values.upnpPort}`);
|
||||
return validDomain;
|
||||
}
|
||||
|
||||
getHostname() {
|
||||
if (this.storageSettings.values.forwardingMode === 'Custom Domain' && this.storageSettings.values.hostname)
|
||||
return this.storageSettings.values.hostname;
|
||||
return SCRYPTED_SERVER;
|
||||
return this.getSSLHostname() || SCRYPTED_SERVER;
|
||||
}
|
||||
|
||||
async convert(data: Buffer, fromMimeType: string): Promise<Buffer> {
|
||||
@@ -571,10 +698,13 @@ class ScryptedCloud extends ScryptedDeviceBase implements OauthClient, Settings,
|
||||
}
|
||||
}
|
||||
else if (url.pathname === '/web/') {
|
||||
if (this.storageSettings.values.forwardingMode === 'Custom Domain' && this.storageSettings.values.hostname)
|
||||
res.setHeader('Location', `https://${this.storageSettings.values.hostname}/endpoint/@scrypted/core/public/`);
|
||||
else
|
||||
const validDomain = this.getSSLHostname();
|
||||
if (validDomain) {
|
||||
res.setHeader('Location', `https://${validDomain}/endpoint/@scrypted/core/public/`);
|
||||
}
|
||||
else {
|
||||
res.setHeader('Location', '/endpoint/@scrypted/core/public/');
|
||||
}
|
||||
res.writeHead(302);
|
||||
res.end();
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user