From 9318658a16a7b03d60c23cd8c1f4364db6594a2b Mon Sep 17 00:00:00 2001 From: Mauro Condarelli Date: Fri, 10 Sep 2021 12:36:44 +0200 Subject: [PATCH 1/6] fix: adapt .gitignore(s) to specific development environment --- .gitignore | 6 ++++-- backend/.gitignore | 48 +++++++++++++++++++++++++++++++++++++++++++++ frontend/.gitignore | 48 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 0a354404..4f8d0146 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ temp .env.test.local .env.production.local +.idea + # Created by https://www.toptal.com/developers/gitignore/api/vscode,yarn,react,node # Edit at https://www.toptal.com/developers/gitignore?templates=vscode,yarn,react,node @@ -156,9 +158,9 @@ sketch # if you are NOT using Zero-installs, then: # comment the following lines -!.yarn/cache +#!.yarn/cache # and uncomment the following lines -# .pnp.* +.pnp.* # End of https://www.toptal.com/developers/gitignore/api/vscode,yarn,react,node \ No newline at end of file diff --git a/backend/.gitignore b/backend/.gitignore index 056fe5c2..fd7d0552 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -33,6 +33,54 @@ jspm_packages/ # Yarn Integrity file .yarn-integrity +# dotenv environment variables file +.env +.env.test +.env.production + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + # Misc .DS_Store .env.local diff --git a/frontend/.gitignore b/frontend/.gitignore index 67dc8992..ab2c4010 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -9,6 +9,54 @@ coverage # Production build +# dotenv environment variables file +.env +.env.test +.env.production + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + # Misc .DS_Store .env.local From 60a307f5628a4ce499ecac1935162bf03e93ed4c Mon Sep 17 00:00:00 2001 From: Mauro Condarelli Date: Fri, 10 Sep 2021 17:38:34 +0200 Subject: [PATCH 2/6] feat: input basic data for ZeroNSd setup Updated Network page Updated save on db.json --- backend/services/network.js | 12 ++++ .../NetworkSettings/NetworkSettings.jsx | 69 ++++++++++++++++--- 2 files changed, 72 insertions(+), 9 deletions(-) diff --git a/backend/services/network.js b/backend/services/network.js index c2a0958d..da1f64ad 100644 --- a/backend/services/network.js +++ b/backend/services/network.js @@ -62,6 +62,9 @@ async function createNetworkAdditionalData(nwid) { additionalConfig: { description: "", rulesSource: constants.defaultRulesSource, + dnsEnable: false, + dnsDomain: "", + dnsWildcard: false, }, members: [], }; @@ -79,6 +82,15 @@ async function updateNetworkAdditionalData(nwid, data) { if (data.hasOwnProperty("rulesSource")) { additionalData.rulesSource = data.rulesSource; } + if (data.hasOwnProperty("dnsEnable")) { + additionalData.dnsEnable = data.dnsEnable; + } + if (data.hasOwnProperty("dnsDomain")) { + additionalData.dnsDomain = data.dnsDomain; + } + if (data.hasOwnProperty("dnsWildcard")) { + additionalData.dnsWildcard = data.dnsWildcard; + } if (additionalData) { db.get("networks") diff --git a/frontend/src/components/NetworkSettings/NetworkSettings.jsx b/frontend/src/components/NetworkSettings/NetworkSettings.jsx index 9378a35f..54ff624c 100644 --- a/frontend/src/components/NetworkSettings/NetworkSettings.jsx +++ b/frontend/src/components/NetworkSettings/NetworkSettings.jsx @@ -8,6 +8,7 @@ import { Typography, TextField, Select, + List, } from "@material-ui/core"; import ExpandMoreIcon from "@material-ui/icons/ExpandMore"; @@ -27,18 +28,18 @@ function NetworkSettings({ network, setNetwork }) { } }; - const handleChange = (key1, key2, mode = "text", additionalData = null) => ( - event - ) => { - const value = parseValue(event, mode, additionalData); + const handleChange = + (key1, key2, mode = "text", additionalData = null) => + (event) => { + const value = parseValue(event, mode, additionalData); - let updatedNetwork = replaceValue({ ...network }, key1, key2, value); - setNetwork(updatedNetwork); + let updatedNetwork = replaceValue({ ...network }, key1, key2, value); + setNetwork(updatedNetwork); - let data = setValue({}, key1, key2, value); + let data = setValue({}, key1, key2, value); - sendReq(data); - }; + sendReq(data); + }; return ( @@ -89,6 +90,56 @@ function NetworkSettings({ network, setNetwork }) { + + ZeroDNS setup + + + + Enable DNS + + + + + + + + + Use wildcards + + From 5ce0bd1009e3e4a3e95121449fae3c6ab78b4c66 Mon Sep 17 00:00:00 2001 From: Mauro Condarelli Date: Fri, 10 Sep 2021 18:08:17 +0200 Subject: [PATCH 3/6] feat: first version actually spawning ZeroNSd --- backend/services/network.js | 15 +++++++++ backend/utils/zns.js | 64 +++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 backend/utils/zns.js diff --git a/backend/services/network.js b/backend/services/network.js index da1f64ad..228214a5 100644 --- a/backend/services/network.js +++ b/backend/services/network.js @@ -4,6 +4,7 @@ const axios = require("axios"); const api = require("../utils/controller-api"); const db = require("../utils/db"); const constants = require("../utils/constants"); +const startStopDNS = require("../utils/zns"); async function getNetworkAdditionalData(data) { let additionalData = db @@ -98,6 +99,20 @@ async function updateNetworkAdditionalData(nwid, data) { .map("additionalConfig") .map((additionalConfig) => _.assign(additionalConfig, additionalData)) .write(); + + if (data.hasOwnProperty("dnsEnable")) { + let token = db.get("users").value()[0]; + token = token.token; + let config = db.get("networks").find({ id: nwid }).value(); + let ret = startStopDNS(token, config.id, config.additionalConfig); + if (ret) { + db.get("networks") + .filter({ id: nwid }) + .map("additionalConfig") + .map((additionalConfig) => _.assign(additionalConfig, ret)) + .write(); + } + } } } diff --git a/backend/utils/zns.js b/backend/utils/zns.js new file mode 100644 index 00000000..9982f435 --- /dev/null +++ b/backend/utils/zns.js @@ -0,0 +1,64 @@ +const { spawn } = require("child_process"); + +function pidIsRunning(pid) { + try { + process.kill(pid, 0); + return true; + } catch (e) { + return false; + } +} + +function startDNS(token, nwid, conf) { + if (conf.hasOwnProperty("pidDNS")) { + if (pidIsRunning(conf.pidDNS)) { + return null; + } + delete conf.pidDNS; + } + const opts = Array("start"); + if (conf.hasOwnProperty("dnsWildcard") && conf.dnsWildcard) { + opts.push("-w"); + } + if (conf.hasOwnProperty("dnsDomain") && !!conf.dnsDomain) { + opts.push("-d", conf.dnsDomain); + } + opts.push(nwid); + let env = process.env; + env.ZEROTIER_CENTRAL_TOKEN = token; + console.log(`*** PATH: "${env.PATH}"`); + const dns = spawn("zeronsd", opts, { + detached: true, + env: env, + }); + dns.on("spawn", () => { + console.log(`zeronsd successfully spawned [${dns.pid}](${dns.spawnargs})`); + console.log("*** should update PID ***"); + }); + dns.on("error", (error) => { + console.log(`zeronsd spawn ERROR: [${error}](${dns.spawnargs})`); + }); + conf.pidDNS = dns.pid; + return conf; +} + +function stopDNS(conf) { + if (conf.hasOwnProperty("pidDNS")) { + try { + process.kill(conf.pidDNS); + } catch (e) {} + delete conf.pidDNS; + return conf; + } + return null; +} + +module.exports = function (token, nwid, conf) { + let ret; + if (conf.dnsEnable) { + ret = startDNS(token, nwid, conf); + } else { + ret = stopDNS(conf); + } + return ret; +}; From 0b77e9594b46c520a5dfa44e1307a9419b813d3d Mon Sep 17 00:00:00 2001 From: Mauro Condarelli Date: Sat, 9 Oct 2021 10:15:13 +0200 Subject: [PATCH 4/6] feat: wip implementation of dns: {...} stanza handling backend/services/network.js implements correct handling of dns: stanza required by ZeroNSd. Unfortunately this breaks frontend. I think this is because of delete statements. Unfortunately I know too little about nodejs to implement a proper solution. I tried mitigating problem using a copy of the data, but that didn't work. Anything else coming to mind seems to ugly to be 'right'. --- backend/services/network.js | 37 ++-- backend/utils/zns.js | 185 +++++++++++++----- .../NetworkSettings/NetworkSettings.jsx | 5 + 3 files changed, 160 insertions(+), 67 deletions(-) diff --git a/backend/services/network.js b/backend/services/network.js index 228214a5..34d7274b 100644 --- a/backend/services/network.js +++ b/backend/services/network.js @@ -4,7 +4,7 @@ const axios = require("axios"); const api = require("../utils/controller-api"); const db = require("../utils/db"); const constants = require("../utils/constants"); -const startStopDNS = require("../utils/zns"); +const zns = require("../utils/zns"); async function getNetworkAdditionalData(data) { let additionalData = db @@ -22,11 +22,22 @@ async function getNetworkAdditionalData(data) { delete data.remoteTraceLevel; delete data.remoteTraceTarget; + let ad = { ...additionalData.value() }; + data.dns = { + domain: ad.dnsDomain, + servers: ["pippo"], + }; + if (ad.dnsIP) data.dns["servers"].push(ad.dnsIP); + console.log(`*** dns="${JSON.stringify(ad)}" -> ${JSON.stringify(data.dns)}`); + delete ad.dnsIP; + delete ad.dnsDomain; + delete ad.dnsEnable; + delete ad.dnsWildcard; return { id: data.id, type: "Network", clock: Math.floor(new Date().getTime() / 1000), - ...additionalData.value(), + ...ad, config: data, }; } @@ -47,13 +58,11 @@ async function getNetworksData(nwids) { return []; }); - let data = Promise.all( + return Promise.all( multipleRes.map((el) => { return getNetworkAdditionalData(el.data); }) ); - - return data; } exports.createNetworkAdditionalData = createNetworkAdditionalData; @@ -84,6 +93,12 @@ async function updateNetworkAdditionalData(nwid, data) { additionalData.rulesSource = data.rulesSource; } if (data.hasOwnProperty("dnsEnable")) { + if (data.dnsEnable) { + //TODO: start ZeroNSd and get its IP address + additionalData.dnsIP = "127.0.0.1"; + } else { + additionalData.dnsIP = null; + } additionalData.dnsEnable = data.dnsEnable; } if (data.hasOwnProperty("dnsDomain")) { @@ -101,17 +116,7 @@ async function updateNetworkAdditionalData(nwid, data) { .write(); if (data.hasOwnProperty("dnsEnable")) { - let token = db.get("users").value()[0]; - token = token.token; - let config = db.get("networks").find({ id: nwid }).value(); - let ret = startStopDNS(token, config.id, config.additionalConfig); - if (ret) { - db.get("networks") - .filter({ id: nwid }) - .map("additionalConfig") - .map((additionalConfig) => _.assign(additionalConfig, ret)) - .write(); - } + zns.handleNet(db.get("networks").filter({ id: nwid }).value()[0]); } } } diff --git a/backend/utils/zns.js b/backend/utils/zns.js index 9982f435..731f167c 100644 --- a/backend/utils/zns.js +++ b/backend/utils/zns.js @@ -1,64 +1,147 @@ -const { spawn } = require("child_process"); +const path = require("path"); +const fs = require("fs"); -function pidIsRunning(pid) { - try { - process.kill(pid, 0); - return true; - } catch (e) { - return false; - } +const db = require("../utils/db"); +const cp = require("child_process"); + +//TODO: does this kind of "optimization" make sense in Node.js? +let token = null; +function getToken() { + if (!token) + try { + token = db.get("users").value()[0].token; + } catch { + console.warn("*** token retrieval failed"); + } + return token; +} + +function setPid(nwid, pid) { + db.get("networks") + .filter({ id: nwid }) + .map("additionalConfig") + .map((additionalConfig) => (additionalConfig.pidDNS = pid)) + .write(); } +const isRunning = (query, pid) => { + return new Promise(function (resolve) { + //FIXME: Check if pgrep is available + cp.exec(`pgrep ${query}`, (err, stdout) => { + resolve(stdout.indexOf(`${pid}`) > -1); + }); + }); +}; + function startDNS(token, nwid, conf) { - if (conf.hasOwnProperty("pidDNS")) { - if (pidIsRunning(conf.pidDNS)) { - return null; + //FIXME: check it does the right thing when conf.pidDNS is null/undefined + isRunning("zeronsd", conf.pidDNS).then((ok) => { + if (ok) { + console.log( + `startDNS(${token}, ${nwid}): already active on PID ${conf.pidDNS}` + ); + } else { + let cmd = "zeronsd"; + let opts = Array(); + if (process.geteuid() === 0) { + // production in Docker container + } else { + // we are debugging + let myLocal = "/home/mcon/.cargo/bin"; + let pth = process.env.PATH.split(path.delimiter); + if (!pth.includes(myLocal)) pth.push(myLocal); + if ( + !process.env.PATH.split(path.delimiter).some(function (d) { + let e = path.resolve(d, cmd); + console.log(`*** PATH testing: "${d}" -> "${e}"`); + try { + fs.accessSync(e, fs.constants.X_OK); + console.log(" is executable"); + cmd = "sudo"; + opts.push("-E", e); + return true; + } catch (e) { + console.warn(` cannot execute (${e})`); + return false; + } + }) + ) { + console.error(`*** zeronsd not found in PATH (${process.env.PATH})`); + return; + } + } + opts.push("start", "-v", "-v"); + if (conf.hasOwnProperty("dnsWildcard") && conf.dnsWildcard) { + opts.push("-w"); + } + if (conf.hasOwnProperty("dnsDomain") && !!conf.dnsDomain) { + opts.push("-d", conf.dnsDomain); + } + opts.push(nwid); + process.env.ZEROTIER_CENTRAL_TOKEN = token; + console.log(`*** PATH: "${process.env.PATH}"`); + console.log( + `*** ZEROTIER_CENTRAL_TOKEN: "${process.env.ZEROTIER_CENTRAL_TOKEN}"` + ); + let dns = cp.spawn(cmd, opts, { detached: true }); + dns.on("spawn", () => { + console.log( + `zeronsd successfully spawned [${dns.pid}](${dns.spawnargs})` + ); + setPid(nwid, dns.pid); + }); + dns.stdout.on("data", (data) => { + console.log(`zeronsd spawn stdout: ${data}`); + }); + dns.stderr.on("data", (data) => { + console.error(`zeronsd spawn stderr: ${data}`); + }); + dns.on("error", (error) => { + console.log(`zeronsd spawn ERROR: [${error}](${dns.spawnargs})`); + }); + dns.on("close", (code) => { + console.log(`zeronsd exited: [${code}](${dns.spawnargs})`); + setPid(nwid, null); + }); } - delete conf.pidDNS; - } - const opts = Array("start"); - if (conf.hasOwnProperty("dnsWildcard") && conf.dnsWildcard) { - opts.push("-w"); - } - if (conf.hasOwnProperty("dnsDomain") && !!conf.dnsDomain) { - opts.push("-d", conf.dnsDomain); - } - opts.push(nwid); - let env = process.env; - env.ZEROTIER_CENTRAL_TOKEN = token; - console.log(`*** PATH: "${env.PATH}"`); - const dns = spawn("zeronsd", opts, { - detached: true, - env: env, - }); - dns.on("spawn", () => { - console.log(`zeronsd successfully spawned [${dns.pid}](${dns.spawnargs})`); - console.log("*** should update PID ***"); - }); - dns.on("error", (error) => { - console.log(`zeronsd spawn ERROR: [${error}](${dns.spawnargs})`); }); - conf.pidDNS = dns.pid; - return conf; } -function stopDNS(conf) { - if (conf.hasOwnProperty("pidDNS")) { - try { - process.kill(conf.pidDNS); - } catch (e) {} - delete conf.pidDNS; - return conf; +function stopDNS(nwid, conf) { + let pid = conf.pidDNS; + if (pid) { + isRunning("zeronsd", pid).then((ok) => { + if (ok) { + console.log(`stopDNS(${nwid}): stopping PID ${pid}`); + try { + process.kill(pid); + } catch (e) { + console.error(`stopDNS(${nwid}): stopping PID ${pid} FAILED (${e})`); + } + } else { + console.log(`stopDNS(${nwid}): PID ${pid} is stale`); + } + }); + setPid(nwid, null); + } else { + console.log(`stopDNS(${nwid}): net has no PID`); } - return null; } -module.exports = function (token, nwid, conf) { - let ret; - if (conf.dnsEnable) { - ret = startDNS(token, nwid, conf); +exports.handleNet = handleNet; +function handleNet(net) { + let cfg = net.additionalConfig; + if (cfg.dnsEnable) { + startDNS(getToken(), net.id, cfg); } else { - ret = stopDNS(conf); + stopDNS(net.id, cfg); } - return ret; -}; +} + +exports.scan = scan; +function scan() { + let nets = db.get("networks").value(); + nets.forEach((net) => { + handleNet(net); + }); +} diff --git a/frontend/src/components/NetworkSettings/NetworkSettings.jsx b/frontend/src/components/NetworkSettings/NetworkSettings.jsx index 54ff624c..855a1be0 100644 --- a/frontend/src/components/NetworkSettings/NetworkSettings.jsx +++ b/frontend/src/components/NetworkSettings/NetworkSettings.jsx @@ -41,6 +41,11 @@ function NetworkSettings({ network, setNetwork }) { sendReq(data); }; + console.log( + `*** dns="${JSON.stringify(network)}" -> ${JSON.stringify( + network["config"] + )}` + ); return ( }> From 0294eb6436e11073e8d857c39f885f97cb7ba794 Mon Sep 17 00:00:00 2001 From: Mauro Condarelli Date: Sun, 10 Oct 2021 19:42:13 +0200 Subject: [PATCH 5/6] feat: frontend back to working status I am unsure about this solution: frontend writes to "additionalConfig" but reads back from `config.dns` maintained by backend. --- backend/services/network.js | 18 +++++++++++++----- backend/utils/zns.js | 6 +++--- .../NetworkSettings/NetworkSettings.jsx | 2 +- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/backend/services/network.js b/backend/services/network.js index 34d7274b..a3a4ba94 100644 --- a/backend/services/network.js +++ b/backend/services/network.js @@ -22,13 +22,21 @@ async function getNetworkAdditionalData(data) { delete data.remoteTraceLevel; delete data.remoteTraceTarget; - let ad = { ...additionalData.value() }; + //let ad = { ...additionalData.value() }; + let ad_ = additionalData.value(); + let ad = JSON.parse(JSON.stringify(ad_)); data.dns = { - domain: ad.dnsDomain, - servers: ["pippo"], + domain: ad_.dnsDomain, + servers: [], }; - if (ad.dnsIP) data.dns["servers"].push(ad.dnsIP); - console.log(`*** dns="${JSON.stringify(ad)}" -> ${JSON.stringify(data.dns)}`); + if (ad_.dnsIP) data.dns["servers"].push(ad_.dnsIP); + console.log( + `*** ad_="${JSON.stringify(ad_, null, 3)}" -> ad="${JSON.stringify( + ad, + null, + 3 + )}" -> ${JSON.stringify(data.dns, null, 3)}` + ); delete ad.dnsIP; delete ad.dnsDomain; delete ad.dnsEnable; diff --git a/backend/utils/zns.js b/backend/utils/zns.js index 731f167c..65cc4287 100644 --- a/backend/utils/zns.js +++ b/backend/utils/zns.js @@ -1,8 +1,8 @@ +const cp = require("child_process"); const path = require("path"); const fs = require("fs"); const db = require("../utils/db"); -const cp = require("child_process"); //TODO: does this kind of "optimization" make sense in Node.js? let token = null; @@ -61,7 +61,7 @@ function startDNS(token, nwid, conf) { opts.push("-E", e); return true; } catch (e) { - console.warn(` cannot execute (${e})`); + console.warn(" cannot execute"); return false; } }) @@ -70,7 +70,7 @@ function startDNS(token, nwid, conf) { return; } } - opts.push("start", "-v", "-v"); + opts.push("start"); if (conf.hasOwnProperty("dnsWildcard") && conf.dnsWildcard) { opts.push("-w"); } diff --git a/frontend/src/components/NetworkSettings/NetworkSettings.jsx b/frontend/src/components/NetworkSettings/NetworkSettings.jsx index 855a1be0..860767dd 100644 --- a/frontend/src/components/NetworkSettings/NetworkSettings.jsx +++ b/frontend/src/components/NetworkSettings/NetworkSettings.jsx @@ -120,7 +120,7 @@ function NetworkSettings({ network, setNetwork }) { /> Date: Sun, 10 Oct 2021 19:46:14 +0200 Subject: [PATCH 6/6] feat: implementation of unified Docker container This creates a Docker container with ZeroTier-One, zero-ui and ZeroNSd all-in-one solution. It also includes a trivial fix to allow ZeroNSd to work with zero-ui. --- docker/all-in-one/Dockerfile | 81 +++++++++++++++++++++++++++++ docker/all-in-one/Dockerfile.debian | 75 ++++++++++++++++++++++++++ docker/all-in-one/entrypoint.sh | 32 ++++++++++++ docker/all-in-one/zeronsd.patch | 12 +++++ 4 files changed, 200 insertions(+) create mode 100644 docker/all-in-one/Dockerfile create mode 100644 docker/all-in-one/Dockerfile.debian create mode 100644 docker/all-in-one/entrypoint.sh create mode 100644 docker/all-in-one/zeronsd.patch diff --git a/docker/all-in-one/Dockerfile b/docker/all-in-one/Dockerfile new file mode 100644 index 00000000..04814530 --- /dev/null +++ b/docker/all-in-one/Dockerfile @@ -0,0 +1,81 @@ +# ---- initialize build stage +FROM node:current-alpine as builder + +# ---- build ZeroTier-One +RUN apk add --update --no-cache alpine-sdk linux-headers \ + && git clone --quiet https://github.com/zerotier/ZeroTierOne.git /src \ + && make -C /src -f make-linux.mk + +# ---- build Zero-UI +ENV INLINE_RUNTIME_CHUNK=false +ENV GENERATE_SOURCEMAP=false + +RUN yarn set version berry + +WORKDIR /app/frontend +COPY ./frontend/package*.json /app/frontend +COPY ./frontend/yarn.lock /app/frontend +RUN yarn install + +COPY ./frontend /app/frontend +RUN yarn build + +# ---- build ZeroNSd \ +FROM rust:alpine as rbuild + +ARG IS_LOCAL=0 +ARG VERSION=main +ARG IS_TAG=0 + +RUN apk add --update --no-cache git libressl-dev musl-dev \ + && git clone https://github.com/zerotier/zeronsd.git \ + && cd zeronsd \ + && sh cargo-docker.sh + +# ---- initialize deploy stage +FROM node:current-alpine + +LABEL description="ZeroTier One as Docker Image" +LABEL org.opencontainers.image.authors="mcondarelli@soft-in.com" + +# ---- copy ZeroTier-One +ARG ZT_VERSION + +LABEL version="${ZT_VERSION}" + +RUN apk add --update --no-cache libc6-compat libstdc++ + +COPY --from=builder /src/zerotier-one /usr/sbin/ +RUN mkdir -p /var/lib/zerotier-one \ + && ln -s /usr/sbin/zerotier-one /usr/sbin/zerotier-idtool \ + && ln -s /usr/sbin/zerotier-one /usr/sbin/zerotier-cli + +EXPOSE 9993/udp + +# ---- copy Zero-UI +WORKDIR /app/frontend/build +COPY --from=builder /app/frontend/build /app/frontend/build/ + +WORKDIR /app/backend +COPY ./backend/package*.json /app/backend +COPY ./backend/yarn.lock /app/backend +RUN yarn install + +COPY ./backend /app/backend + +EXPOSE 4000 +ENV NODE_ENV=production +ENV ZU_SECURE_HEADERS=true +ENV ZU_SERVE_FRONTEND=true + +# ---- copy ZeroNSd +COPY --from=rbuild /usr/local/cargo/bin/zeronsd /usr/sbin/ + +# ---- final setup + +VOLUME /var/lib/zerotier + +COPY docker/all-in-one/entrypoint.sh /entrypoint.sh +RUN chmod 755 /entrypoint.sh + +CMD /entrypoint.sh diff --git a/docker/all-in-one/Dockerfile.debian b/docker/all-in-one/Dockerfile.debian new file mode 100644 index 00000000..31830b80 --- /dev/null +++ b/docker/all-in-one/Dockerfile.debian @@ -0,0 +1,75 @@ +# ---- initialize build stage +FROM node:current-bullseye as builder + +# ---- build ZeroTier-One +RUN apt-get update && apt-get install -y build-essential \ + && git clone --quiet https://github.com/zerotier/ZeroTierOne.git /src \ + && make -C /src -f make-linux.mk + +# ---- build Zero-UI +ENV INLINE_RUNTIME_CHUNK=false +ENV GENERATE_SOURCEMAP=false + +RUN yarn set version berry + +WORKDIR /app/frontend +COPY ./frontend/package*.json /app/frontend +COPY ./frontend/yarn.lock /app/frontend +RUN yarn install + +COPY ./frontend /app/frontend +RUN yarn build + +# ---- build ZeroNSd \ +FROM rust:bullseye as rbuild + +ARG IS_LOCAL=0 +ARG VERSION=main +ARG IS_TAG=0 + +COPY ./docker/all-in-one/zeronsd.patch /tmp/zeronsd.patch +RUN apt-get update && apt-get install --no-install-recommends -y git libssl-dev \ + && git clone https://github.com/zerotier/zeronsd.git \ + && cd zeronsd \ + && patch -p 1 /dev/null | grep -q zerotier-one + return $? +} + +echo "starting zerotier" +setsid /usr/sbin/zerotier-one & + +while ! grepzt +do + echo "zerotier hasn't started, waiting a second" + sleep 1 +done + +echo "joining networks" + +for i in "$@" +do + echo "joining $i" + + while ! zerotier-cli join "$i" + do + echo "joining $i failed; trying again in 1s" + sleep 1 + done +done + +echo "starting node" +node ./bin/www +echo "at end" diff --git a/docker/all-in-one/zeronsd.patch b/docker/all-in-one/zeronsd.patch new file mode 100644 index 00000000..81627c31 --- /dev/null +++ b/docker/all-in-one/zeronsd.patch @@ -0,0 +1,12 @@ +diff --git a/src/utils.rs b/src/utils.rs +index 0f62d52..0f90e69 100644 +--- a/src/utils.rs ++++ b/src/utils.rs +@@ -21,6 +21,7 @@ pub(crate) fn central_config(token: String) -> Configuration { + let mut config = Configuration::default(); + config.user_agent = Some(version()); + config.bearer_access_token = Some(token); ++ config.base_path = "http://localhost:3000/api".to_string(); + return config; + } +