Merge branch 'master' into switch-authenticated-health-checks-to-api-key
This commit is contained in:
commit
12906dffdb
|
@ -66,7 +66,6 @@ services:
|
|||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
- NEXT_PUBLIC_SKYNET_PORTAL_API=${SKYNET_PORTAL_API}
|
||||
- NEXT_PUBLIC_PORTAL_DOMAIN=${PORTAL_DOMAIN}
|
||||
- NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=${STRIPE_PUBLISHABLE_KEY}
|
||||
volumes:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM openresty/openresty:1.19.9.1-bionic
|
||||
FROM openresty/openresty:1.19.9.1-focal
|
||||
|
||||
RUN luarocks install lua-resty-http && \
|
||||
luarocks install hasher && \
|
||||
|
|
|
@ -81,8 +81,8 @@ proxy_pass https://127.0.0.1/$skylink$path$is_args$args;
|
|||
|
||||
# in case siad returns location header, we need to replace the skylink with the domain name
|
||||
header_filter_by_lua_block {
|
||||
ngx.header["Skynet-Portal-Api"] = os.getenv("SKYNET_PORTAL_API")
|
||||
ngx.header["Skynet-Server-Api"] = os.getenv("SKYNET_SERVER_API")
|
||||
ngx.header["Skynet-Portal-Api"] = ngx.var.scheme .. "://" .. os.getenv("PORTAL_DOMAIN")
|
||||
ngx.header["Skynet-Server-Api"] = ngx.var.scheme .. "://" .. os.getenv("SERVER_DOMAIN")
|
||||
|
||||
if ngx.header.location then
|
||||
-- match location redirect part after the skylink
|
||||
|
|
|
@ -82,8 +82,8 @@ access_by_lua_block {
|
|||
}
|
||||
|
||||
header_filter_by_lua_block {
|
||||
ngx.header["Skynet-Portal-Api"] = os.getenv("SKYNET_PORTAL_API")
|
||||
ngx.header["Skynet-Server-Api"] = os.getenv("SKYNET_SERVER_API")
|
||||
ngx.header["Skynet-Portal-Api"] = ngx.var.scheme .. "://" .. os.getenv("PORTAL_DOMAIN")
|
||||
ngx.header["Skynet-Server-Api"] = ngx.var.scheme .. "://" .. os.getenv("SERVER_DOMAIN")
|
||||
|
||||
-- not empty skynet_proof means this is a skylink v2 request
|
||||
-- so we should replace the Skynet-Proof header with the one
|
||||
|
|
|
@ -248,8 +248,8 @@ location /skynet/tus {
|
|||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# rewrite proxy request to use correct host uri from env variable (required to return correct location header)
|
||||
set_by_lua $SKYNET_SERVER_API 'return os.getenv("SKYNET_SERVER_API")';
|
||||
proxy_redirect $scheme://$host $SKYNET_SERVER_API;
|
||||
set_by_lua_block $server_domain { return os.getenv("SERVER_DOMAIN") }
|
||||
proxy_redirect $scheme://$host $scheme://$server_domain;
|
||||
|
||||
# proxy /skynet/tus requests to siad endpoint with all arguments
|
||||
proxy_pass http://sia:9980;
|
||||
|
@ -276,8 +276,8 @@ location /skynet/tus {
|
|||
|
||||
# extract skylink from base64 encoded upload metadata and assign to a proper header
|
||||
header_filter_by_lua_block {
|
||||
ngx.header["Skynet-Portal-Api"] = os.getenv("SKYNET_PORTAL_API")
|
||||
ngx.header["Skynet-Server-Api"] = os.getenv("SKYNET_SERVER_API")
|
||||
ngx.header["Skynet-Portal-Api"] = ngx.var.scheme .. "://" .. os.getenv("PORTAL_DOMAIN")
|
||||
ngx.header["Skynet-Server-Api"] = ngx.var.scheme .. "://" .. os.getenv("SERVER_DOMAIN")
|
||||
|
||||
if ngx.header["Upload-Metadata"] then
|
||||
local encodedSkylink = string.match(ngx.header["Upload-Metadata"], "Skylink ([^,?]+)")
|
||||
|
@ -311,8 +311,8 @@ location /skynet/metadata {
|
|||
include /etc/nginx/conf.d/include/portal-access-check;
|
||||
|
||||
header_filter_by_lua_block {
|
||||
ngx.header["Skynet-Portal-Api"] = os.getenv("SKYNET_PORTAL_API")
|
||||
ngx.header["Skynet-Server-Api"] = os.getenv("SKYNET_SERVER_API")
|
||||
ngx.header["Skynet-Portal-Api"] = ngx.var.scheme .. "://" .. os.getenv("PORTAL_DOMAIN")
|
||||
ngx.header["Skynet-Server-Api"] = ngx.var.scheme .. "://" .. os.getenv("SERVER_DOMAIN")
|
||||
}
|
||||
|
||||
proxy_set_header User-Agent: Sia-Agent;
|
||||
|
@ -324,8 +324,8 @@ location /skynet/resolve {
|
|||
include /etc/nginx/conf.d/include/portal-access-check;
|
||||
|
||||
header_filter_by_lua_block {
|
||||
ngx.header["Skynet-Portal-Api"] = os.getenv("SKYNET_PORTAL_API")
|
||||
ngx.header["Skynet-Server-Api"] = os.getenv("SKYNET_SERVER_API")
|
||||
ngx.header["Skynet-Portal-Api"] = ngx.var.scheme .. "://" .. os.getenv("PORTAL_DOMAIN")
|
||||
ngx.header["Skynet-Server-Api"] = ngx.var.scheme .. "://" .. os.getenv("SERVER_DOMAIN")
|
||||
}
|
||||
|
||||
proxy_set_header User-Agent: Sia-Agent;
|
||||
|
@ -348,6 +348,43 @@ location ~ "^/file/(([a-zA-Z0-9-_]{46}|[a-z0-9]{55})(/.*)?)$" {
|
|||
include /etc/nginx/conf.d/include/location-skylink;
|
||||
}
|
||||
|
||||
location /skynet/trustless/basesector {
|
||||
include /etc/nginx/conf.d/include/cors;
|
||||
include /etc/nginx/conf.d/include/proxy-buffer;
|
||||
include /etc/nginx/conf.d/include/track-download;
|
||||
|
||||
limit_conn downloads_by_ip 100; # ddos protection: max 100 downloads at a time
|
||||
|
||||
# default download rate to unlimited
|
||||
set $limit_rate 0;
|
||||
|
||||
access_by_lua_block {
|
||||
if require("skynet.account").accounts_enabled() then
|
||||
-- check if portal is in authenticated only mode
|
||||
if require("skynet.account").is_access_unauthorized() then
|
||||
return require("skynet.account").exit_access_unauthorized()
|
||||
end
|
||||
|
||||
-- check if portal is in subscription only mode
|
||||
if require("skynet.account").is_access_forbidden() then
|
||||
return require("skynet.account").exit_access_forbidden()
|
||||
end
|
||||
|
||||
-- get account limits of currently authenticated user
|
||||
local limits = require("skynet.account").get_account_limits()
|
||||
|
||||
-- apply download speed limit
|
||||
ngx.var.limit_rate = limits.download
|
||||
end
|
||||
}
|
||||
|
||||
limit_rate_after 512k;
|
||||
limit_rate $limit_rate;
|
||||
|
||||
proxy_set_header User-Agent: Sia-Agent;
|
||||
proxy_pass http://sia:9980;
|
||||
}
|
||||
|
||||
location /__internal/do/not/use/accounts {
|
||||
include /etc/nginx/conf.d/include/cors;
|
||||
|
||||
|
|
|
@ -26,8 +26,8 @@ worker_processes auto;
|
|||
#pid logs/nginx.pid;
|
||||
|
||||
# declare env variables to use it in config
|
||||
env SKYNET_PORTAL_API;
|
||||
env SKYNET_SERVER_API;
|
||||
env PORTAL_DOMAIN;
|
||||
env SERVER_DOMAIN;
|
||||
env PORTAL_MODULES;
|
||||
env ACCOUNTS_LIMIT_ACCESS;
|
||||
env SIA_API_PASSWORD;
|
||||
|
@ -95,8 +95,8 @@ http {
|
|||
|
||||
# include skynet-portal-api and skynet-server-api header on every request
|
||||
header_filter_by_lua_block {
|
||||
ngx.header["Skynet-Portal-Api"] = os.getenv("SKYNET_PORTAL_API")
|
||||
ngx.header["Skynet-Server-Api"] = os.getenv("SKYNET_SERVER_API")
|
||||
ngx.header["Skynet-Portal-Api"] = ngx.var.scheme .. "://" .. os.getenv("PORTAL_DOMAIN")
|
||||
ngx.header["Skynet-Server-Api"] = ngx.var.scheme .. "://" .. os.getenv("SERVER_DOMAIN")
|
||||
}
|
||||
|
||||
# ratelimit specified IPs
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
node_modules/
|
||||
.cache/
|
||||
public
|
|
@ -0,0 +1,10 @@
|
|||
# Skynet Account Dashboard
|
||||
|
||||
Code behind [account.skynetpro.net](https://account.skynetpro.net/)
|
||||
|
||||
|
||||
## Development
|
||||
This is a Gatsby application. To run it locally, all you need is:
|
||||
|
||||
* `yarn install`
|
||||
* `yarn start`
|
|
@ -0,0 +1,13 @@
|
|||
import React from "react";
|
||||
import "@fontsource/sora/300.css"; // light
|
||||
import "@fontsource/sora/400.css"; // normal
|
||||
import "@fontsource/sora/500.css"; // medium
|
||||
import "@fontsource/sora/600.css"; // semibold
|
||||
import "@fontsource/source-sans-pro/400.css"; // normal
|
||||
import "@fontsource/source-sans-pro/600.css"; // semibold
|
||||
import "./src/styles/global.css";
|
||||
|
||||
export function wrapPageElement({ element, props }) {
|
||||
const Layout = element.type.Layout ?? React.Fragment
|
||||
return <Layout {...props}>{element}</Layout>
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
module.exports = {
|
||||
siteMetadata: {
|
||||
title: `Accounts Dashboard`,
|
||||
siteUrl: `https://www.yourdomain.tld`
|
||||
},
|
||||
plugins: [
|
||||
"gatsby-plugin-image",
|
||||
"gatsby-plugin-react-helmet",
|
||||
"gatsby-plugin-sharp",
|
||||
"gatsby-transformer-sharp",
|
||||
"gatsby-plugin-postcss", {
|
||||
resolve: 'gatsby-source-filesystem',
|
||||
options: {
|
||||
"name": "images",
|
||||
"path": "./src/images/"
|
||||
},
|
||||
__key: "images"
|
||||
}, {
|
||||
resolve: `gatsby-plugin-alias-imports`,
|
||||
options: {
|
||||
alias: {
|
||||
// Allows npm link-ing skynet-storybook during development.
|
||||
"styled-components": "./node_modules/styled-components",
|
||||
},
|
||||
extensions: [
|
||||
"js",
|
||||
],
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
"name": "accounts-dashboard",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Accounts Dashboard",
|
||||
"author": "Skynet Labs",
|
||||
"keywords": [
|
||||
"gatsby"
|
||||
],
|
||||
"scripts": {
|
||||
"develop": "gatsby develop",
|
||||
"start": "gatsby develop",
|
||||
"build": "gatsby build",
|
||||
"serve": "gatsby serve",
|
||||
"clean": "gatsby clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource/sora": "^4.5.0",
|
||||
"@fontsource/source-sans-pro": "^4.5.1",
|
||||
"babel-plugin-styled-components": "^2.0.2",
|
||||
"gatsby": "^4.6.2",
|
||||
"gatsby-plugin-image": "^2.6.0",
|
||||
"gatsby-plugin-react-helmet": "^5.6.0",
|
||||
"gatsby-plugin-sharp": "^4.6.0",
|
||||
"gatsby-plugin-styled-components": "^5.7.0",
|
||||
"gatsby-source-filesystem": "^4.6.0",
|
||||
"gatsby-transformer-sharp": "^4.6.0",
|
||||
"react": "^17.0.1",
|
||||
"react-dom": "^17.0.1",
|
||||
"react-helmet": "^6.1.0",
|
||||
"tailwindcss": "^3.0.22"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^10.4.2",
|
||||
"gatsby-plugin-alias-imports": "^1.0.5",
|
||||
"gatsby-plugin-postcss": "^5.7.0",
|
||||
"postcss": "^8.4.6",
|
||||
"styled-components": "^5.3.3"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
plugins: [require("tailwindcss"), require("autoprefixer")],
|
||||
};
|
|
@ -0,0 +1,54 @@
|
|||
import * as React from "react"
|
||||
import { Link } from "gatsby"
|
||||
|
||||
// styles
|
||||
const pageStyles = {
|
||||
color: "#232129",
|
||||
padding: "96px",
|
||||
fontFamily: "-apple-system, Roboto, sans-serif, serif",
|
||||
}
|
||||
const headingStyles = {
|
||||
marginTop: 0,
|
||||
marginBottom: 64,
|
||||
maxWidth: 320,
|
||||
}
|
||||
|
||||
const paragraphStyles = {
|
||||
marginBottom: 48,
|
||||
}
|
||||
const codeStyles = {
|
||||
color: "#8A6534",
|
||||
padding: 4,
|
||||
backgroundColor: "#FFF4DB",
|
||||
fontSize: "1.25rem",
|
||||
borderRadius: 4,
|
||||
}
|
||||
|
||||
// markup
|
||||
const NotFoundPage = () => {
|
||||
return (
|
||||
<main style={pageStyles}>
|
||||
<title>Not found</title>
|
||||
<h1 style={headingStyles}>Page not found</h1>
|
||||
<p style={paragraphStyles}>
|
||||
Sorry{" "}
|
||||
<span role="img" aria-label="Pensive emoji">
|
||||
😔
|
||||
</span>{" "}
|
||||
we couldn’t find what you were looking for.
|
||||
<br />
|
||||
{process.env.NODE_ENV === "development" ? (
|
||||
<>
|
||||
<br />
|
||||
Try creating a page in <code style={codeStyles}>src/pages/</code>.
|
||||
<br />
|
||||
</>
|
||||
) : null}
|
||||
<br />
|
||||
<Link to="/">Go home</Link>.
|
||||
</p>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
export default NotFoundPage
|
|
@ -0,0 +1,13 @@
|
|||
import * as React from "react"
|
||||
|
||||
// markup
|
||||
const FilesPage = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
FILES
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default FilesPage
|
|
@ -0,0 +1,13 @@
|
|||
import * as React from "react"
|
||||
|
||||
// markup
|
||||
const IndexPage = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
Dashboard
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default IndexPage
|
|
@ -0,0 +1,3 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
|
@ -0,0 +1,70 @@
|
|||
const defaultTheme = require("tailwindcss/defaultTheme");
|
||||
const plugin = require("tailwindcss/plugin");
|
||||
|
||||
const colors = {
|
||||
primary: { light: "#33D17E", DEFAULT: "#00c65e" },
|
||||
warning: "#ffd567",
|
||||
error: "#ED5454",
|
||||
palette: {
|
||||
100: "#f5f7f7",
|
||||
200: "#d4dddb",
|
||||
300: "#9e9e9e",
|
||||
400: "#555555",
|
||||
500: "#242424",
|
||||
600: "#0d0d0d",
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
content: [
|
||||
"./src/**/*.{js,jsx,ts,tsx}",
|
||||
"./node_modules/skynet-storybook/dist/**/*.{js,jsx,ts,tsx}", // Also apply Tailwind classes to our shared components library
|
||||
],
|
||||
theme: {
|
||||
screens: {
|
||||
sm: "640px",
|
||||
md: "768px",
|
||||
lg: "1024px",
|
||||
xl: "1440px",
|
||||
},
|
||||
backgroundColor: (theme) => ({ ...theme("colors"), ...colors }),
|
||||
borderColor: (theme) => ({ ...theme("colors"), ...colors }),
|
||||
textColor: (theme) => ({ ...theme("colors"), ...colors }),
|
||||
placeholderColor: (theme) => ({ ...theme("colors"), ...colors }),
|
||||
extend: {
|
||||
fontFamily: {
|
||||
sans: ["Sora", ...defaultTheme.fontFamily.sans],
|
||||
content: ["Source\\ Sans\\ Pro", ...defaultTheme.fontFamily.sans],
|
||||
},
|
||||
fontSize: {
|
||||
tab: ["18px", "28px"],
|
||||
},
|
||||
backgroundColor: ["disabled"],
|
||||
textColor: ["disabled"],
|
||||
keyframes: {
|
||||
wiggle: {
|
||||
"0%, 100%": { transform: "rotate(-3deg)" },
|
||||
"50%": { transform: "rotate(3deg)" },
|
||||
},
|
||||
},
|
||||
animation: {
|
||||
wiggle: "wiggle 3s ease-in-out infinite",
|
||||
},
|
||||
width: {
|
||||
page: "100%",
|
||||
"page-md": "640px",
|
||||
"page-lg": "896px",
|
||||
"page-xl": "1312px",
|
||||
}
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
plugin(function ({ addBase, theme }) {
|
||||
addBase({
|
||||
body: {
|
||||
color: theme("textColor.palette.600"),
|
||||
},
|
||||
});
|
||||
}),
|
||||
],
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -20,7 +20,7 @@
|
|||
"formik": "2.2.9",
|
||||
"http-status-codes": "2.2.0",
|
||||
"ky": "0.28.7",
|
||||
"next": "12.0.10",
|
||||
"next": "12.1.0",
|
||||
"normalize.css": "8.0.1",
|
||||
"pretty-bytes": "6.0.0",
|
||||
"react": "17.0.2",
|
||||
|
|
|
@ -82,7 +82,7 @@ export default function Layout({ title, children }) {
|
|||
</a>
|
||||
</Link>
|
||||
<a
|
||||
href={process.env.NEXT_PUBLIC_SKYNET_PORTAL_API}
|
||||
href={`https://${process.env.NEXT_PUBLIC_PORTAL_DOMAIN}`}
|
||||
className="text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium flex items-center"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
|
@ -234,7 +234,7 @@ export default function Layout({ title, children }) {
|
|||
</a>
|
||||
</Link>
|
||||
<a
|
||||
href={process.env.NEXT_PUBLIC_SKYNET_PORTAL_API}
|
||||
href={`https://${process.env.NEXT_PUBLIC_PORTAL_DOMAIN}`}
|
||||
className="text-gray-300 hover:bg-gray-700 hover:text-white block px-3 py-2 rounded-md text-base font-medium flex items-center"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
|
|
|
@ -6,7 +6,7 @@ import Table from "../components/Table";
|
|||
import { SkynetClient } from "skynet-js";
|
||||
import useAccountsApi from "../services/useAccountsApi";
|
||||
|
||||
const skynetClient = new SkynetClient(process.env.NEXT_PUBLIC_SKYNET_PORTAL_API);
|
||||
const skynetClient = new SkynetClient(`https://${process.env.NEXT_PUBLIC_PORTAL_DOMAIN}`);
|
||||
const getSkylinkLink = ({ skylink }) => skynetClient.getSkylinkUrl(skylink);
|
||||
const getRelativeDate = ({ downloadedOn }) => dayjs(downloadedOn).format("YYYY-MM-DD HH:mm:ss");
|
||||
const headers = [
|
||||
|
|
|
@ -11,7 +11,7 @@ import React from "react";
|
|||
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
const skynetClient = new SkynetClient(process.env.NEXT_PUBLIC_SKYNET_PORTAL_API);
|
||||
const skynetClient = new SkynetClient(`https://${process.env.NEXT_PUBLIC_PORTAL_DOMAIN}`);
|
||||
|
||||
function SkylinkList({ items = [], timestamp }) {
|
||||
return (
|
||||
|
|
|
@ -8,7 +8,7 @@ import Table from "../components/Table";
|
|||
import { SkynetClient } from "skynet-js";
|
||||
import useAccountsApi from "../services/useAccountsApi";
|
||||
|
||||
const skynetClient = new SkynetClient(process.env.NEXT_PUBLIC_SKYNET_PORTAL_API);
|
||||
const skynetClient = new SkynetClient(`https://${process.env.NEXT_PUBLIC_PORTAL_DOMAIN}`);
|
||||
const getSkylinkLink = ({ skylink }) => skynetClient.getSkylinkUrl(skylink);
|
||||
const getRelativeDate = ({ uploadedOn }) => dayjs(uploadedOn).format("YYYY-MM-DD HH:mm:ss");
|
||||
const headers = [
|
||||
|
|
|
@ -77,10 +77,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
|
||||
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
|
||||
|
||||
"@next/env@12.0.10":
|
||||
version "12.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.0.10.tgz#561640fd62279218ccd2798ae907bae8d94a7730"
|
||||
integrity sha512-mQVj0K6wQ5WEk/sL9SZ+mJXJUaG7el8CpZ6io1uFe9GgNTSC7EgUyNGqM6IQovIFc5ukF4O/hqsdh3S/DCgT2g==
|
||||
"@next/env@12.1.0":
|
||||
version "12.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.1.0.tgz#73713399399b34aa5a01771fb73272b55b22c314"
|
||||
integrity sha512-nrIgY6t17FQ9xxwH3jj0a6EOiQ/WDHUos35Hghtr+SWN/ntHIQ7UpuvSi0vaLzZVHQWaDupKI+liO5vANcDeTQ==
|
||||
|
||||
"@next/eslint-plugin-next@12.0.10":
|
||||
version "12.0.10"
|
||||
|
@ -89,60 +89,60 @@
|
|||
dependencies:
|
||||
glob "7.1.7"
|
||||
|
||||
"@next/swc-android-arm64@12.0.10":
|
||||
version "12.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.0.10.tgz#fd9d716433cc9d361021b0052f8b002bcaff948d"
|
||||
integrity sha512-xYwXGkNhzZZsM5MD7KRwF5ZNiC8OLPtVMUiagpPnwENg8Hb0GSQo/NbYWXM8YrawEwp9LaZ7OXiuRKPh2JyBdA==
|
||||
"@next/swc-android-arm64@12.1.0":
|
||||
version "12.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.1.0.tgz#865ba3a9afc204ff2bdeea49dd64d58705007a39"
|
||||
integrity sha512-/280MLdZe0W03stA69iL+v6I+J1ascrQ6FrXBlXGCsGzrfMaGr7fskMa0T5AhQIVQD4nA/46QQWxG//DYuFBcA==
|
||||
|
||||
"@next/swc-darwin-arm64@12.0.10":
|
||||
version "12.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.0.10.tgz#34b2d0dc62eb89efb9176af111e3820a11fdb3f0"
|
||||
integrity sha512-f2zngulkpIJKWHckhRi7X8GZ+J/tNgFF7lYIh7Qx15JH0OTBsjkqxORlkzy+VZyHJ5sWTCaI6HYYd3ow6qkEEg==
|
||||
"@next/swc-darwin-arm64@12.1.0":
|
||||
version "12.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.1.0.tgz#08e8b411b8accd095009ed12efbc2f1d4d547135"
|
||||
integrity sha512-R8vcXE2/iONJ1Unf5Ptqjk6LRW3bggH+8drNkkzH4FLEQkHtELhvcmJwkXcuipyQCsIakldAXhRbZmm3YN1vXg==
|
||||
|
||||
"@next/swc-darwin-x64@12.0.10":
|
||||
version "12.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.0.10.tgz#a4306795159293c7d4d58a2c88ce1710ff0a8baa"
|
||||
integrity sha512-Qykcu/gVC5oTvOQoRBhyuS5GYm5SbcgrFTsaLFkGBmEkg9eMQRiaCswk4IafpDXVzITkVFurzSM28q3tLW2qUw==
|
||||
"@next/swc-darwin-x64@12.1.0":
|
||||
version "12.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.1.0.tgz#fcd684497a76e8feaca88db3c394480ff0b007cd"
|
||||
integrity sha512-ieAz0/J0PhmbZBB8+EA/JGdhRHBogF8BWaeqR7hwveb6SYEIJaDNQy0I+ZN8gF8hLj63bEDxJAs/cEhdnTq+ug==
|
||||
|
||||
"@next/swc-linux-arm-gnueabihf@12.0.10":
|
||||
version "12.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.0.10.tgz#1ad15af3d5fca2fef57894d61e16f73aee61ec2e"
|
||||
integrity sha512-EhqrTFsIXAXN9B/fiiW/QKUK/lSLCXRsLalkUp58KDfMqVLLlj1ORbESAcswiNQOChLuHQSldGEEtOBPQZcd9A==
|
||||
"@next/swc-linux-arm-gnueabihf@12.1.0":
|
||||
version "12.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.1.0.tgz#9ec6380a27938a5799aaa6035c205b3c478468a7"
|
||||
integrity sha512-njUd9hpl6o6A5d08dC0cKAgXKCzm5fFtgGe6i0eko8IAdtAPbtHxtpre3VeSxdZvuGFh+hb0REySQP9T1ttkog==
|
||||
|
||||
"@next/swc-linux-arm64-gnu@12.0.10":
|
||||
version "12.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.0.10.tgz#a84a92d0e1a179c4346c9ed8f22e26f708101ad6"
|
||||
integrity sha512-kqGtC72g3+JYXZbY2ca6digXR5U6AQ6Dzv4eAxYluMePLHjI/Xye1mf9dwVsgmeXfrD/IRDp5K/3A6UNvBm4oQ==
|
||||
"@next/swc-linux-arm64-gnu@12.1.0":
|
||||
version "12.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.1.0.tgz#7f4196dff1049cea479607c75b81033ae2dbd093"
|
||||
integrity sha512-OqangJLkRxVxMhDtcb7Qn1xjzFA3s50EIxY7mljbSCLybU+sByPaWAHY4px97ieOlr2y4S0xdPKkQ3BCAwyo6Q==
|
||||
|
||||
"@next/swc-linux-arm64-musl@12.0.10":
|
||||
version "12.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.0.10.tgz#973ec96c77f845bd0a6eecbf1892caa1ee4defaf"
|
||||
integrity sha512-bG9zTSNwnSgc1Un/7oz1ZVN4UeXsTWrsQhAGWU78lLLCn4Zj9HQoUCRCGLt0OVs2DBZ+WC8CzzFliQ1SKipVbg==
|
||||
"@next/swc-linux-arm64-musl@12.1.0":
|
||||
version "12.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.1.0.tgz#b445f767569cdc2dddee785ca495e1a88c025566"
|
||||
integrity sha512-hB8cLSt4GdmOpcwRe2UzI5UWn6HHO/vLkr5OTuNvCJ5xGDwpPXelVkYW/0+C3g5axbDW2Tym4S+MQCkkH9QfWA==
|
||||
|
||||
"@next/swc-linux-x64-gnu@12.0.10":
|
||||
version "12.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.0.10.tgz#efcc7f8252ea8225834760eaf09350f1bead73f7"
|
||||
integrity sha512-c79PcfWtyThiYRa1+3KVfDq0zXaI8o1d6dQWNVqDrtLz5HKM/rbjLdvoNuxDwUeZhxI/d9CtyH6GbuKPw5l/5A==
|
||||
"@next/swc-linux-x64-gnu@12.1.0":
|
||||
version "12.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.1.0.tgz#67610e9be4fbc987de7535f1bcb17e45fe12f90e"
|
||||
integrity sha512-OKO4R/digvrVuweSw/uBM4nSdyzsBV5EwkUeeG4KVpkIZEe64ZwRpnFB65bC6hGwxIBnTv5NMSnJ+0K/WmG78A==
|
||||
|
||||
"@next/swc-linux-x64-musl@12.0.10":
|
||||
version "12.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.0.10.tgz#c2a73d939dfd310acc1892a0a132762500dd5757"
|
||||
integrity sha512-g/scgn+21/MLfizOCZOZt+MxNj2/8Tdlwjvy+QZcSUPZRUI2Y5o3HwBvI1f/bSci+NGRU+bUAO0NFtRJ9MzH5w==
|
||||
"@next/swc-linux-x64-musl@12.1.0":
|
||||
version "12.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.1.0.tgz#ea19a23db08a9f2e34ac30401f774cf7d1669d31"
|
||||
integrity sha512-JohhgAHZvOD3rQY7tlp7NlmvtvYHBYgY0x5ZCecUT6eCCcl9lv6iV3nfu82ErkxNk1H893fqH0FUpznZ/H3pSw==
|
||||
|
||||
"@next/swc-win32-arm64-msvc@12.0.10":
|
||||
version "12.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.0.10.tgz#2316af5f612cde1691abdf2571ff40ec32ea3429"
|
||||
integrity sha512-gl6B/ravwMeY5Nv4Il2/ARYJQ6u+KPRwGMjS1ZrNudIKlNn4YBeXh5A4cIVm+dHaff6/O/lGOa5/SUYDMZpkww==
|
||||
"@next/swc-win32-arm64-msvc@12.1.0":
|
||||
version "12.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.1.0.tgz#eadf054fc412085659b98e145435bbba200b5283"
|
||||
integrity sha512-T/3gIE6QEfKIJ4dmJk75v9hhNiYZhQYAoYm4iVo1TgcsuaKLFa+zMPh4056AHiG6n9tn2UQ1CFE8EoybEsqsSw==
|
||||
|
||||
"@next/swc-win32-ia32-msvc@12.0.10":
|
||||
version "12.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.0.10.tgz#98a4f74d164871cfaccb0df6efddf2b7bcbaa54b"
|
||||
integrity sha512-7RVpZ3tSThC6j+iZB0CUYmFiA3kXmN+pE7QcfyAxFaflKlaZoWNMKHIEZDuxSJc6YmQ6kyxsjqxVay2F5+/YCg==
|
||||
"@next/swc-win32-ia32-msvc@12.1.0":
|
||||
version "12.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.1.0.tgz#68faeae10c89f698bf9d28759172b74c9c21bda1"
|
||||
integrity sha512-iwnKgHJdqhIW19H9PRPM9j55V6RdcOo6rX+5imx832BCWzkDbyomWnlzBfr6ByUYfhohb8QuH4hSGEikpPqI0Q==
|
||||
|
||||
"@next/swc-win32-x64-msvc@12.0.10":
|
||||
version "12.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.0.10.tgz#5c0ba98b695c4be44d8793aff42971a0dac65c2d"
|
||||
integrity sha512-oUIWRKd24jFLRWUYO1CZmML5+32BcpVfqhimGaaZIXcOkfQW+iqiAzdqsv688zaGtyKGeB9ZtiK3NDf+Q0v+Vw==
|
||||
"@next/swc-win32-x64-msvc@12.1.0":
|
||||
version "12.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.1.0.tgz#d27e7e76c87a460a4da99c5bfdb1618dcd6cd064"
|
||||
integrity sha512-aBvcbMwuanDH4EMrL2TthNJy+4nP59Bimn8egqv6GHMVj0a44cU6Au4PjOhLNqEh9l+IpRGBqMTzec94UdC5xg==
|
||||
|
||||
"@nodelib/fs.scandir@2.1.5":
|
||||
version "2.1.5"
|
||||
|
@ -1691,28 +1691,28 @@ natural-compare@^1.4.0:
|
|||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
|
||||
|
||||
next@12.0.10:
|
||||
version "12.0.10"
|
||||
resolved "https://registry.yarnpkg.com/next/-/next-12.0.10.tgz#fcc4584177418bd777ce157f3165b7ba5e7708f7"
|
||||
integrity sha512-1y3PpGzpb/EZzz1jgne+JfZXKAVJUjYXwxzrADf/LWN+8yi9o79vMLXpW3mevvCHkEF2sBnIdjzNn16TJrINUw==
|
||||
next@12.1.0:
|
||||
version "12.1.0"
|
||||
resolved "https://registry.yarnpkg.com/next/-/next-12.1.0.tgz#c33d753b644be92fc58e06e5a214f143da61dd5d"
|
||||
integrity sha512-s885kWvnIlxsUFHq9UGyIyLiuD0G3BUC/xrH0CEnH5lHEWkwQcHOORgbDF0hbrW9vr/7am4ETfX4A7M6DjrE7Q==
|
||||
dependencies:
|
||||
"@next/env" "12.0.10"
|
||||
"@next/env" "12.1.0"
|
||||
caniuse-lite "^1.0.30001283"
|
||||
postcss "8.4.5"
|
||||
styled-jsx "5.0.0"
|
||||
use-subscription "1.5.1"
|
||||
optionalDependencies:
|
||||
"@next/swc-android-arm64" "12.0.10"
|
||||
"@next/swc-darwin-arm64" "12.0.10"
|
||||
"@next/swc-darwin-x64" "12.0.10"
|
||||
"@next/swc-linux-arm-gnueabihf" "12.0.10"
|
||||
"@next/swc-linux-arm64-gnu" "12.0.10"
|
||||
"@next/swc-linux-arm64-musl" "12.0.10"
|
||||
"@next/swc-linux-x64-gnu" "12.0.10"
|
||||
"@next/swc-linux-x64-musl" "12.0.10"
|
||||
"@next/swc-win32-arm64-msvc" "12.0.10"
|
||||
"@next/swc-win32-ia32-msvc" "12.0.10"
|
||||
"@next/swc-win32-x64-msvc" "12.0.10"
|
||||
"@next/swc-android-arm64" "12.1.0"
|
||||
"@next/swc-darwin-arm64" "12.1.0"
|
||||
"@next/swc-darwin-x64" "12.1.0"
|
||||
"@next/swc-linux-arm-gnueabihf" "12.1.0"
|
||||
"@next/swc-linux-arm64-gnu" "12.1.0"
|
||||
"@next/swc-linux-arm64-musl" "12.1.0"
|
||||
"@next/swc-linux-x64-gnu" "12.1.0"
|
||||
"@next/swc-linux-x64-musl" "12.1.0"
|
||||
"@next/swc-win32-arm64-msvc" "12.1.0"
|
||||
"@next/swc-win32-ia32-msvc" "12.1.0"
|
||||
"@next/swc-win32-x64-msvc" "12.1.0"
|
||||
|
||||
node-releases@^2.0.1:
|
||||
version "2.0.1"
|
||||
|
|
|
@ -38,7 +38,7 @@ require("yargs/yargs")(process.argv.slice(2))
|
|||
})
|
||||
.option("portal-url", {
|
||||
describe: "Skynet portal url",
|
||||
default: process.env.SKYNET_PORTAL_API || "https://siasky.net",
|
||||
default: process.env.PORTAL_DOMAIN ? `https://${process.env.PORTAL_DOMAIN}` : "https://siasky.net",
|
||||
type: "string",
|
||||
})
|
||||
.option("state-dir", {
|
||||
|
@ -48,7 +48,8 @@ require("yargs/yargs")(process.argv.slice(2))
|
|||
});
|
||||
},
|
||||
async ({ type, portalUrl, stateDir }) => {
|
||||
process.env.SKYNET_PORTAL_API = portalUrl;
|
||||
const { hostname: portalDomain } = new URL(portalUrl); // extract domain from portal url
|
||||
process.env.PORTAL_DOMAIN = portalDomain;
|
||||
process.env.STATE_DIR = stateDir;
|
||||
|
||||
const util = require("util");
|
||||
|
|
|
@ -6,9 +6,10 @@ const { SkynetClient, stringToUint8ArrayUtf8, genKeyPairAndSeed } = require("sky
|
|||
|
||||
const MODULE_BLOCKER = "b";
|
||||
|
||||
const skynetClient = new SkynetClient(process.env.SKYNET_PORTAL_API, {
|
||||
const skynetClient = new SkynetClient(`https://${process.env.PORTAL_DOMAIN}`, {
|
||||
skynetApiKey: process.env.ACCOUNTS_TEST_USER_API_KEY,
|
||||
});
|
||||
|
||||
const exampleSkylink = "AACogzrAimYPG42tDOKhS3lXZD8YvlF8Q8R17afe95iV2Q";
|
||||
|
||||
// check that any relevant configuration is properly set in skyd
|
||||
|
@ -46,7 +47,7 @@ async function uploadCheck(done) {
|
|||
form.append("file", payload, { filename: "time.txt", contentType: "text/plain" });
|
||||
|
||||
try {
|
||||
const response = await got.post(`${process.env.SKYNET_PORTAL_API}/skynet/skyfile`, {
|
||||
const response = await got.post(`https://${process.env.PORTAL_DOMAIN}/skynet/skyfile`, {
|
||||
body: form,
|
||||
headers: {
|
||||
"Skynet-Api-Key": process.env.ACCOUNTS_TEST_USER_API_KEY,
|
||||
|
@ -68,7 +69,7 @@ async function uploadCheck(done) {
|
|||
|
||||
// websiteCheck checks whether the main website is working
|
||||
async function websiteCheck(done) {
|
||||
return done(await genericAccessCheck("website", process.env.SKYNET_PORTAL_API));
|
||||
return done(await genericAccessCheck("website", `https://${process.env.PORTAL_DOMAIN}`));
|
||||
}
|
||||
|
||||
// downloadCheck returns the result of downloading the hard coded link
|
||||
|
@ -132,13 +133,13 @@ async function registryWriteAndReadCheck(done) {
|
|||
|
||||
// directServerApiAccessCheck returns the basic server api check on direct server address
|
||||
async function directServerApiAccessCheck(done) {
|
||||
if (!process.env.SKYNET_SERVER_API) {
|
||||
return done({ up: false, errors: [{ message: "SKYNET_SERVER_API env variable not configured" }] });
|
||||
if (!process.env.SERVER_DOMAIN) {
|
||||
return done({ up: false, errors: [{ message: "SERVER_DOMAIN env variable not configured" }] });
|
||||
}
|
||||
|
||||
const [portalAccessCheck, serverAccessCheck] = await Promise.all([
|
||||
genericAccessCheck("portal_api_access", process.env.SKYNET_PORTAL_API),
|
||||
genericAccessCheck("server_api_access", process.env.SKYNET_SERVER_API),
|
||||
genericAccessCheck("portal_api_access", `https://${process.env.PORTAL_DOMAIN}`),
|
||||
genericAccessCheck("server_api_access", `https://${process.env.SERVER_DOMAIN}`),
|
||||
]);
|
||||
|
||||
if (portalAccessCheck.ip !== serverAccessCheck.ip) {
|
||||
|
@ -147,8 +148,8 @@ async function directServerApiAccessCheck(done) {
|
|||
serverAccessCheck.errors.push({
|
||||
message: "Access ip mismatch between portal and server access",
|
||||
response: {
|
||||
portal: { name: process.env.SKYNET_PORTAL_API, ip: portalAccessCheck.ip },
|
||||
server: { name: process.env.SKYNET_SERVER_API, ip: serverAccessCheck.ip },
|
||||
portal: { name: process.env.PORTAL_DOMAIN, ip: portalAccessCheck.ip },
|
||||
server: { name: process.env.SERVER_DOMAIN, ip: serverAccessCheck.ip },
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1134,7 +1134,7 @@ async function skylinkVerification(done, expected, { followRedirect = true, meth
|
|||
const details = { name: expected.name, skylink: expected.skylink };
|
||||
|
||||
try {
|
||||
const query = `${process.env.SKYNET_PORTAL_API}/${expected.skylink}`;
|
||||
const query = `https://${process.env.PORTAL_DOMAIN}/${expected.skylink}`;
|
||||
const response = await got[method](query, {
|
||||
followRedirect,
|
||||
headers: {
|
||||
|
@ -1176,7 +1176,7 @@ async function skylinkVerification(done, expected, { followRedirect = true, meth
|
|||
|
||||
if (expected.metadata && expected.skylink) {
|
||||
const skylink = parseSkylink(expected.skylink);
|
||||
const url = `${process.env.SKYNET_PORTAL_API}/skynet/metadata/${skylink}`;
|
||||
const url = `https://${process.env.PORTAL_DOMAIN}/skynet/metadata/${skylink}`;
|
||||
try {
|
||||
const metadata = await got(url, { headers: { cookie: `nocache=true;${authCookie}` } }).json();
|
||||
if (!isEqual(expected.metadata, metadata)) {
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
process.env.NODE_ENV = process.env.NODE_ENV || "development";
|
||||
|
||||
if (!process.env.SKYNET_PORTAL_API) {
|
||||
throw new Error("You need to provide SKYNET_PORTAL_API environment variable");
|
||||
}
|
||||
|
||||
if (!process.env.PORTAL_DOMAIN) {
|
||||
throw new Error("You need to provide PORTAL_DOMAIN environment variable");
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ async def send_msg(msg, force_notify=False, file=None):
|
|||
webhook = DiscordWebhook(url=webhook_url, rate_limit_retry=True)
|
||||
|
||||
# Add the portal name.
|
||||
msg = "**{}**: {}".format(os.getenv("SKYNET_SERVER_API"), msg)
|
||||
msg = "**{}**: {}".format(os.getenv("SERVER_DOMAIN"), msg)
|
||||
|
||||
if file and isinstance(file, str):
|
||||
is_json = is_json_string(file)
|
||||
|
|
|
@ -23,8 +23,6 @@ docker-compose --version # sanity check
|
|||
# Create dummy .env file for docker-compose usage with variables
|
||||
# * PORTAL_DOMAIN - (required) is a skynet portal domain (ex. siasky.net)
|
||||
# * SERVER_DOMAIN - (optional) is an optional direct server domain (ex. eu-ger-1.siasky.net) - leave blank unless it is different than PORTAL_DOMAIN
|
||||
# * SKYNET_PORTAL_API - absolute url to the portal api ie. https://siasky.net (general portal address)
|
||||
# * SKYNET_SERVER_API - absolute url to the server api ie. https://eu-ger-1.siasky.net (direct server address, if this is single server portal use the same address as SKYNET_PORTAL_API)
|
||||
# * EMAIL_ADDRESS - this is the administrator contact email you need to supply for communication regarding SSL certification
|
||||
# * HSD_API_KEY - this is auto generated secure key for your handshake service integration
|
||||
# * CLOUDFLARE_AUTH_TOKEN - (optional) if using cloudflare as dns loadbalancer (need to change it in Caddyfile too)
|
||||
|
@ -43,7 +41,7 @@ docker-compose --version # sanity check
|
|||
# * COOKIE_ENC_KEY - (optional) if using `accounts` encryption key, at least 32 bytes
|
||||
if ! [ -f /home/user/skynet-webportal/.env ]; then
|
||||
HSD_API_KEY=$(openssl rand -base64 32) # generate safe random key for handshake
|
||||
printf "PORTAL_DOMAIN=siasky.net\nSERVER_DOMAIN=\nSKYNET_PORTAL_API=https://siasky.net\nSKYNET_SERVER_API=https://eu-dc-1.siasky.net\nEMAIL_ADDRESS=email@example.com\nSIA_WALLET_PASSWORD=\nHSD_API_KEY=${HSD_API_KEY}\nCLOUDFLARE_AUTH_TOKEN=\nAWS_ACCESS_KEY_ID=\nAWS_SECRET_ACCESS_KEY=\nDISCORD_WEBHOOK_URL=\nDISCORD_MENTION_USER_ID=\nDISCORD_MENTION_ROLE_ID=\n" > /home/user/skynet-webportal/.env
|
||||
printf "PORTAL_DOMAIN=siasky.net\nSERVER_DOMAIN=\nEMAIL_ADDRESS=email@example.com\nSIA_WALLET_PASSWORD=\nHSD_API_KEY=${HSD_API_KEY}\nCLOUDFLARE_AUTH_TOKEN=\nAWS_ACCESS_KEY_ID=\nAWS_SECRET_ACCESS_KEY=\nDISCORD_WEBHOOK_URL=\nDISCORD_MENTION_USER_ID=\nDISCORD_MENTION_ROLE_ID=\n" > /home/user/skynet-webportal/.env
|
||||
fi
|
||||
|
||||
# Start docker container with nginx and client
|
||||
|
|
Reference in New Issue