public ManagerSite AddSite(ManagerAddSite cmd, IManagerCommandLogger logger)
        {
            //Generate a new ID
            long id;

            while (true)
            {
                //Create
                byte[] idBytes = new byte[8];
                rand.NextBytes(idBytes);
                id = Math.Abs(BitConverter.ToInt64(idBytes));

                //Check
                if (!sites.ContainsKey(id.ToString()))
                {
                    break;
                }
            }

            //Create site data
            ManagerSite site = new ManagerSite
            {
                id            = id.ToString(),
                cert_name     = "DeltaManagedCert_" + id.ToString(),
                document_root = cmd.document_root,
                proxies       = new LibDeltaSystem.CoreNet.NetMessages.Master.Entities.NetManagerSite_Proxy[]
                {
                    new LibDeltaSystem.CoreNet.NetMessages.Master.Entities.NetManagerSite_Proxy
                    {
                        to_path   = "/",
                        from_path = cmd.proxy_root,
                        proto     = cmd.proto
                    }
                },
                site_domain = cmd.domain,
                cert_expiry = DateTime.UtcNow.AddMonths(3)
            };

            //Create+sign SSL certificate
            logger?.Log("AddSite", "Creating and signing a new SSL certificate...");
            int status = CLITool.RunCLIProcess("certbot", $"certonly -n --cert-name {site.cert_name} --standalone --preferred-challenges http -d {site.site_domain}", logger, "AddSite", "Creating and signing SSL certificate...");

            if (status != 0)
            {
                logger?.FinishFail($"Could not create SSL certificate! (Code {status})");
                return(null);
            }

            //Add
            sites.Add(site.id, site);
            Save();

            //Finish
            RefreshSites();
            logger.FinishSuccess($"Successfully added site {site.site_domain}.");

            return(site);
        }
        public ManagerVersion BuildUpdatedVersion(ManagerSession session, IManagerCommandLogger logger, string topic)
        {
            //Download the update
            logger.Log(topic, "Downloading new updates...");
            if (DownloadUpdate(session, logger, topic) != 0)
            {
                logger.FinishFail("Failed to download updates. Aborting!");
                return(null);
            }

            //Create new version ID
            string id = ObjectId.GenerateNewId().ToString();

            while (session.versions.ContainsKey(id))
            {
                id = ObjectId.GenerateNewId().ToString();
            }

            //Create new version
            ManagerVersion version = new ManagerVersion
            {
                id           = id,
                package_name = name,
                time         = DateTime.UtcNow
            };

            //Create output folder
            Directory.CreateDirectory(version.GetPath(session));

            //Build new version
            logger.Log(topic, "Building version from source...");
            if (CLITool.RunCLIProcess(session.dotnet_path, $"build -o {version.GetPath(session)} {GetProjectPath(session)}", logger, topic, "Building project files...") != 0)
            {
                logger.FinishFail("Failed to build project. Aborting!");
                return(null);
            }

            //Add to versions
            lock (session.versions)
                session.versions.Add(id, version);
            latest_version = version.id;
            session.Save();

            //Log
            logger.FinishSuccess($"Successfully created new version {version.id} for package {version.package_name}.");

            return(version);
        }
        /// <summary>
        /// Refreshes the sites for Apache2
        /// </summary>
        public bool RefreshSites()
        {
            //Build site file
            string balancersPart = "";
            string sitesPart     = "";

            //Write each site
            foreach (var s in sites)
            {
                //Add each balancer
                List <string> addedBalancers = new List <string>();
                foreach (var p in s.Value.proxies)
                {
                    if (addedBalancers.Contains(p.proto))
                    {
                        continue;
                    }
                    balancersPart += CreateBalancerString(s.Value, p.proto);
                    addedBalancers.Add(p.proto);
                }

                //Create base for sites
                string baseData = $"\t#DELTA MANAGED SITE {s.Key}\n\tServerName {s.Value.site_domain}\n\tServerAdmin webmaster@localhost\n\tDocumentRoot {s.Value.document_root}\n\tProxyPreserveHost On\n";
                foreach (var p in s.Value.proxies)
                {
                    baseData += $"\tProxyPass \"{p.from_path}\" \"balancer://DeltaManagedBalancer_{s.Value.id}_{p.proto}{p.to_path}\"\n\tProxyPassReverse \"{p.from_path}\" \"balancer://DeltaManagedBalancer_{s.Value.id}_{p.proto}{p.to_path}\"\n";
                }

                //Write SSL and HTTP hosts
                sitesPart += $"<VirtualHost *:80>\n{baseData}</VirtualHost>\n";
                sitesPart += $"<VirtualHost *:443>\n{baseData}\tInclude /etc/letsencrypt/options-ssl-apache.conf\n\tSSLCertificateFile {CERT_ROOT_PATH}{s.Value.cert_name}/fullchain.pem\n\tSSLCertificateKeyFile {CERT_ROOT_PATH}{s.Value.cert_name}/privkey.pem\n</VirtualHost>\n";
            }

            //Save
            File.WriteAllText("/etc/apache2/sites-available/delta-managed-sites.conf", $"#THIS FILE IS AUTOMATICALLY MANAGED BY DELTAWEBMAP MACHINE MANAGER.\n#EDITS WILL BE OVERWRITTEN.\n{balancersPart}{sitesPart}");

            //Refresh
            return(0 == CLITool.RunTerminalCommand("service apache2 reload", null, null, null));
        }