v0.0.8 Automatic HTTPS certificate provisioning

This commit is contained in:
Yann Stepienik 2023-03-27 18:52:54 +01:00
parent eeec876234
commit 1fea4ef573
18 changed files with 272 additions and 151 deletions

View File

@ -0,0 +1,4 @@
name: Feature Request
about: Request a new feature
title: "[FEAT]: "
labels: [feature, review]

60
.github/ISSUE_TEMPLATE/issue report.yml vendored Normal file
View File

@ -0,0 +1,60 @@
name: Issue Report
description: File an issue report
title: "[BUG]: "
labels: [bug, review]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: textarea
id: what-happened
attributes:
label: What happened?
description: "A clear and concise description of what the bug is."
placeholder: "When I do X, I see Y."
validations:
required: true
- type: textarea
id: what-should-happen
attributes:
label: What should have happened?
description: "A clear and concise description of what you expected to happen."
placeholder: "When I do X, I should see Z."
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: How to reproduce the bug?
description: "A clear and concise description of how to reproduce the bug."
placeholder: "Steps to reproduce the behavior:"
value: |
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
validations:
required: true
- type: textarea
id: logs
attributes:
label: Relevant log output
description: "Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks."
render: shell
- type: textarea
id: other-details
attributes:
label: Other details
description: "Anything else you'd like to add?"
- type: textarea
id: system-details
attributes:
label: System details
description: "Please fill out the following details about your system depending on how relevant (always include Cosmos Version!)."
value: |
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
validations:
required: true

View File

@ -1,5 +1,5 @@
// assets
import { GithubOutlined, QuestionOutlined } from '@ant-design/icons';
import { GithubOutlined, QuestionOutlined, BugOutlined } from '@ant-design/icons';
import DiscordOutlined from '../assets/images/icons/discord.svg'
import DiscordOutlinedWhite from '../assets/images/icons/discord_white.svg'
import { useTheme } from '@mui/material/styles';
@ -45,6 +45,15 @@ const support = {
icon: QuestionOutlined,
external: true,
target: true
},
{
id: 'bug',
title: 'Found a Bug?',
type: 'item',
url: 'https://github.com/azukaar/Cosmos-Server/issues/new/choose',
icon: BugOutlined,
external: true,
target: true
}
]
};

View File

@ -28,6 +28,7 @@ import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons';
import AnimateButton from '../../../components/@extended/AnimateButton';
import RestartModal from './restart';
import { WarningOutlined, PlusCircleOutlined, CopyOutlined, ExclamationCircleOutlined , SyncOutlined, UserOutlined, KeyOutlined } from '@ant-design/icons';
import { CosmosInputText, CosmosSelect } from './formShortcuts';
const ConfigManagement = () => {
@ -61,6 +62,8 @@ const ConfigManagement = () => {
GenerateMissingAuthCert: config.HTTPConfig.GenerateMissingAuthCert,
HTTPPort: config.HTTPConfig.HTTPPort,
HTTPSPort: config.HTTPConfig.HTTPSPort,
SSLEmail: config.HTTPConfig.SSLEmail,
HTTPSCertificateMode: config.HTTPConfig.HTTPSCertificateMode,
}}
validationSchema={Yup.object().shape({
Hostname: Yup.string().max(255).required('Hostname is required'),
@ -76,10 +79,11 @@ const ConfigManagement = () => {
HTTPConfig: {
...config.HTTPConfig,
Hostname: values.Hostname,
GenerateMissingTLSCert: values.GenerateMissingTLSCert,
GenerateMissingAuthCert: values.GenerateMissingAuthCert,
HTTPPort: values.HTTPPort,
HTTPSPort: values.HTTPSPort,
SSLEmail: values.SSLEmail,
HTTPSCertificateMode: values.HTTPSCertificateMode,
}
}
@ -106,8 +110,8 @@ const ConfigManagement = () => {
}
}}
>
{({ errors, handleBlur, handleChange, handleSubmit, isSubmitting, touched, values }) => (
<form noValidate onSubmit={handleSubmit}>
{(formik) => (
<form noValidate onSubmit={formik.handleSubmit}>
<MainCard title="General">
<Grid container spacing={3}>
<Grid item xs={12}>
@ -119,17 +123,17 @@ const ConfigManagement = () => {
<OutlinedInput
id="MongoDB-login"
type="password"
value={values.MongoDB}
value={formik.values.MongoDB}
name="MongoDB"
onBlur={handleBlur}
onChange={handleChange}
onBlur={formik.handleBlur}
onChange={formik.handleChange}
placeholder="MongoDB"
fullWidth
error={Boolean(touched.MongoDB && errors.MongoDB)}
error={Boolean(formik.touched.MongoDB && formik.errors.MongoDB)}
/>
{touched.MongoDB && errors.MongoDB && (
{formik.touched.MongoDB && formik.errors.MongoDB && (
<FormHelperText error id="standard-weight-helper-text-MongoDB-login">
{errors.MongoDB}
{formik.errors.MongoDB}
</FormHelperText>
)}
</Stack>
@ -144,14 +148,14 @@ const ConfigManagement = () => {
name="LoggingLevel"
id="LoggingLevel"
select
value={values.LoggingLevel}
onChange={handleChange}
value={formik.values.LoggingLevel}
onChange={formik.handleChange}
error={
touched.LoggingLevel &&
Boolean(errors.LoggingLevel)
formik.touched.LoggingLevel &&
Boolean(formik.errors.LoggingLevel)
}
helperText={
touched.LoggingLevel && errors.LoggingLevel
formik.touched.LoggingLevel && formik.errors.LoggingLevel
}
>
<MenuItem key={"DEBUG"} value={"DEBUG"}>
@ -182,17 +186,17 @@ const ConfigManagement = () => {
<OutlinedInput
id="Hostname-login"
type="text"
value={values.Hostname}
value={formik.values.Hostname}
name="Hostname"
onBlur={handleBlur}
onChange={handleChange}
onBlur={formik.handleBlur}
onChange={formik.handleChange}
placeholder="Hostname"
fullWidth
error={Boolean(touched.Hostname && errors.Hostname)}
error={Boolean(formik.touched.Hostname && formik.errors.Hostname)}
/>
{touched.Hostname && errors.Hostname && (
{formik.touched.Hostname && formik.errors.Hostname && (
<FormHelperText error id="standard-weight-helper-text-Hostname-login">
{errors.Hostname}
{formik.errors.Hostname}
</FormHelperText>
)}
</Stack>
@ -204,17 +208,17 @@ const ConfigManagement = () => {
<OutlinedInput
id="HTTPPort-login"
type="text"
value={values.HTTPPort}
value={formik.values.HTTPPort}
name="HTTPPort"
onBlur={handleBlur}
onChange={handleChange}
onBlur={formik.handleBlur}
onChange={formik.handleChange}
placeholder="HTTPPort"
fullWidth
error={Boolean(touched.HTTPPort && errors.HTTPPort)}
error={Boolean(formik.touched.HTTPPort && formik.errors.HTTPPort)}
/>
{touched.HTTPPort && errors.HTTPPort && (
{formik.touched.HTTPPort && formik.errors.HTTPPort && (
<FormHelperText error id="standard-weight-helper-text-HTTPPort-login">
{errors.HTTPPort}
{formik.errors.HTTPPort}
</FormHelperText>
)}
</Stack>
@ -226,17 +230,17 @@ const ConfigManagement = () => {
<OutlinedInput
id="HTTPSPort-login"
type="text"
value={values.HTTPSPort}
value={formik.values.HTTPSPort}
name="HTTPSPort"
onBlur={handleBlur}
onChange={handleChange}
onBlur={formik.handleBlur}
onChange={formik.handleChange}
placeholder="HTTPSPort"
fullWidth
error={Boolean(touched.HTTPSPort && errors.HTTPSPort)}
error={Boolean(formik.touched.HTTPSPort && formik.errors.HTTPSPort)}
/>
{touched.HTTPSPort && errors.HTTPSPort && (
{formik.touched.HTTPSPort && formik.errors.HTTPSPort && (
<FormHelperText error id="standard-weight-helper-text-HTTPSPort-login">
{errors.HTTPSPort}
{formik.errors.HTTPSPort}
</FormHelperText>
)}
</Stack>
@ -249,17 +253,28 @@ const ConfigManagement = () => {
<Grid item xs={12}>
<Alert severity="info">For security reasons, It is not possible to remotely change the Private keys of any certificates on your instance. It is advised to manually edit the config file, or better, use Environment Variables to store them.</Alert>
</Grid>
<Grid item xs={12}>
<Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}>
<Field
type="checkbox"
name="GenerateMissingTLSCert"
as={FormControlLabel}
control={<Checkbox size="large" />}
label="Generate missing HTTPS Certificates automatically (Default: true)"
<CosmosSelect
name="HTTPSCertificateMode"
label="HTTPS Certificates"
formik={formik}
options={[
["LETSENCRYPT", "Automatically generate certificates using Let's Encrypt (Recommended)"],
["SELFSIGNED", "Locally self-sign certificates (unsecure)"],
["PROVIDED", "I have my own certificates"],
["DISABLED", "Do not use HTTPS (very unsecure)"],
]}
/>
{
formik.values.HTTPSCertificateMode === "LETSENCRYPT" && (
<CosmosInputText
name="SSLEmail"
label="Email address for Let's Encrypt"
formik={formik}
/>
</Stack>
</Grid>
)
}
<Grid item xs={12}>
<Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}>
@ -297,16 +312,16 @@ const ConfigManagement = () => {
<br /><br />
<MainCard>
{errors.submit && (
{formik.errors.submit && (
<Grid item xs={12}>
<FormHelperText error>{errors.submit}</FormHelperText>
<FormHelperText error>{formik.errors.submit}</FormHelperText>
</Grid>
)}
<Grid item xs={12}>
<AnimateButton>
<Button
disableElevation
disabled={isSubmitting}
disabled={formik.isSubmitting}
fullWidth
size="large"
type="submit"

View File

@ -1,5 +1,5 @@
// material-ui
import { Typography } from '@mui/material';
import { Alert, Typography } from '@mui/material';
import { useState } from 'react';
// project import
@ -11,9 +11,8 @@ const ServeApps = () => {
const {serveApps, setServeApps} = useState([]);
return <div>
Nothing Yet :)
<Alert severity="info">Implementation currently in progress! If you want to voice your opinion on where Cosmos is going, please join us on Discord!</Alert>
</div>
}
export default ServeApps;

View File

@ -7,6 +7,7 @@ import UserManagement from '../pages/config/users/usermanagement';
import ConfigManagement from '../pages/config/users/configman';
import ProxyManagement from '../pages/config/users/proxyman';
import ServeApps from '../pages/servapps/servapps';
import { Navigate } from 'react-router';
// render - dashboard
const DashboardDefault = Loadable(lazy(() => import('../pages/dashboard')));
@ -26,6 +27,11 @@ const MainRoutes = {
path: '/',
element: <MainLayout />,
children: [
{
path: '/',
// redirect to /ui
element: <Navigate to="/ui" />
},
{
path: '/ui/',
element: <DashboardDefault />

Binary file not shown.

Before

Width:  |  Height:  |  Size: 700 KiB

After

Width:  |  Height:  |  Size: 700 KiB

BIN
diag_SN2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 KiB

View File

@ -18,7 +18,7 @@ sh build arm64.sh
docker build \
-t azukaar/cosmos-server:$VERSION-arm64 \
-t azukaar/cosmos-server:latest-arm64 \
-f Dockerfile.arm64 \
-f dockerfile.arm64 \
--platform linux/arm64 \
.

View File

@ -1,6 +1,6 @@
{
"name": "cosmos-server",
"version": "0.0.7",
"version": "0.0.8",
"description": "",
"main": "test-server.js",
"bugs": {

View File

@ -14,11 +14,12 @@ Cosmos is a server platform for running self-hosted applications securely and wi
Whether you have a **server**, a **NAS**, or a **Raspberry Pi** with applications such as **Plex**, **HomeAssistant** or even a blog, Cosmos is the perfect solution to secure it all. Simply install Cosmos on your server and connect to your applications through it to enjoy built-in security and robustness for all your services, right out of the box.
* **Authentication** Connect to all your application with the same account, including strong security and **multi-factor authentication**
* **Automatic HTTPS** certificates provision
* **Anti-bot** protections such as Captcha and IP rate limiting
* **Anti-DDOS** protections such as variable timeouts/throttling, IP rate limiting and IP blacklisting
* **Proper user management** to invite your friends and family to your applications without awkardly sharing credentials. Let them request a password change with an email rather than having you unlock their account manually!
* **Authentication** 👦👩 Connect to all your application with the same account, including strong security and **multi-factor authentication**
* **Automatic HTTPS** 🔑📜 certificates provision
* **Anti-Bot** 🤖❌ protections such as Captcha and IP rate limiting
* **Anti-DDOS** 🔥⛔️ protections such as variable timeouts/throttling, IP rate limiting and IP blacklisting
* **Proper User Management** 🪪 ❎ to invite your friends and family to your applications without awkardly sharing credentials. Let them request a password change with an email rather than having you unlock their account manually!
* **Container Management** 🧱🔧 to easily manage your containers and their settings, keep them up to date as well as audit their security.
And a **lot more planned features** are coming!
@ -34,6 +35,10 @@ It is becoming an important **threat to you**. Managing servers, applications an
It is even more important since most tools used to self-host **not specifically designed to be secure for your scenario**. Entreprise tools such as Traefik, NGinx, etc... Are designed for different use-cases that assume that the code you are running behind them is **not malicious**. But who knows what server apps you might be running? On top of that, a lot of reverse-proxies and security tools lock important security features behind 3 to 4 figures business subscriptions that are not realistic for selfhosting. Here's a simple example of how Cosmos can help you:
![diag_SN](./diag_SN2.png)
Another example:
![diag_SN](./diag_SN.png)
Another big issue is, because every new self-hosted applications **re-invent the wheel** and implement **crucial systems** such as authentication **from scratch** everytime, the **large majority** of them are very succeptible to being **hacked without too much trouble**.
@ -47,35 +52,10 @@ That is the issue Cosmos Server is trying to solve: by providing a secure and ro
Installation is simple using Docker:
```
docker run -d -p 80:80 -p 443:443 -v /path/to/cosmos/config:/config azukaar/cosmos-server:latest
docker run -d -p 80:80 -p 443:443 --name cosmos-server --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v /path/to/cosmos/config:/config azukaar/cosmos-server:latest
```
you can use `latest-arm64` for arm architecture (ex: NAS or Raspberry)
You can thing tweak the config file accordingly. Some settings can be changed before end with env var. [see here](https://github.com/azukaar/Cosmos-Server/wiki/Configuration).
# How to contribute
## Setup
You need [GuPM](https://github.com/azukaar/GuPM) with the [provider-go](https://github.com/azukaar/GuPM-official#provider-go) plugin to run this project.
```
g make
```
## Run locally
First create a file called dev.json with:
```json
{
"MONGODB": "your mongodb connection string"
}
```
```
g build
g start # this will run server
g client # this will run the client
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 714 KiB

After

Width:  |  Height:  |  Size: 658 KiB

View File

@ -47,7 +47,13 @@ func connect() error {
DockerClient = client
DockerContext = ctx
CreateCosmosNetwork()
ping, err := DockerClient.Ping(DockerContext)
if ping.APIVersion != "" && err == nil {
utils.Log("Docker Connected")
} else {
utils.Error("Docker Connection - Cannot ping Daemon. Is it running?", nil)
return errors.New("Docker Connection - Cannot ping Daemon. Is it running?")
}
// if running in Docker, connect to main network
// if os.Getenv("HOSTNAME") != "" {

View File

@ -11,6 +11,7 @@ import (
func DockerListenEvents() error {
errD := connect()
if errD != nil {
utils.Error("Docker did not connect. Not listening", errD)
return errD
}
@ -20,7 +21,10 @@ func DockerListenEvents() error {
for {
select {
case err := <-errs:
utils.Error("Docker Events", err)
if err == nil {
return
}
utils.Error("Docker Event Error", err)
case msg := <-msgs:
utils.Debug("Docker Event: " + msg.Type + " " + msg.Action + " " + msg.Actor.ID)
if msg.Type == "container" && msg.Action == "start" {

View File

@ -8,16 +8,17 @@ import (
"github.com/azukaar/cosmos-server/src/proxy"
"github.com/azukaar/cosmos-server/src/docker"
"github.com/gorilla/mux"
"strings"
"strconv"
"time"
"encoding/json"
"os"
"strings"
"github.com/go-chi/chi/middleware"
"github.com/go-chi/httprate"
"crypto/tls"
spa "github.com/roberthodgen/spa-server"
// "github.com/foomo/simplecert"
"github.com/foomo/simplecert"
"github.com/foomo/tlsconfig"
)
var serverPortHTTP = ""
@ -34,73 +35,87 @@ func startHTTPServer(router *mux.Router) {
}
func startHTTPSServer(router *mux.Router, tlsCert string, tlsKey string) {
// cfg := simplecert.Default
// cfg.Domains = []string{"yourdomain.com", "www.yourdomain.com"}
// cfg.CacheDir = "/etc/letsencrypt/live/yourdomain.com"
// cfg.SSLEmail = "you@emailprovider.com"
// cfg.DNSProvider = "cloudflare"
// certReloader, err := simplecert.Init(cfg, nil)
// if err != nil {
// utils.Fatal("simplecert init failed: ", err)
// }
config := utils.GetMainConfig()
// check if Docker overwrite Hostname
serverHostname := "0.0.0.0" //utils.GetMainConfig().HTTPConfig.Hostname
// if os.Getenv("HOSTNAME") != "" {
// serverHostname = os.Getenv("HOSTNAME")
// }
cfg := simplecert.Default
cfg.Domains = utils.GetAllHostnames()
cfg.CacheDir = "/config/certificates"
cfg.SSLEmail = config.HTTPConfig.SSLEmail
cfg.HTTPAddress = serverHostname+":"+serverPortHTTP
cfg.TLSAddress = serverHostname+":"+serverPortHTTPS
var certReloader *simplecert.CertReloader
var errSimCert error
if(config.HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["LETSENCRYPT"]) {
certReloader, errSimCert = simplecert.Init(cfg, nil)
if errSimCert != nil {
utils.Fatal("simplecert init failed: ", errSimCert)
}
}
// redirect http to https
go (func () {
err := http.ListenAndServe("0.0.0.0:" + serverPortHTTP, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// change port in host
if strings.HasSuffix(r.Host, ":" + serverPortHTTP) {
if serverPortHTTPS != "443" {
r.Host = r.Host[:len(r.Host)-len(":" + serverPortHTTP)] + ":" + serverPortHTTPS
} else {
r.Host = r.Host[:len(r.Host)-len(":" + serverPortHTTP)]
}
// redirect http to https
go (func () {
// err := http.ListenAndServe("0.0.0.0:" + serverPortHTTP, http.HandlerFunc(simplecert.Redirect))
err := http.ListenAndServe("0.0.0.0:" + serverPortHTTP, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// change port in host
if strings.HasSuffix(r.Host, ":" + serverPortHTTP) {
if serverPortHTTPS != "443" {
r.Host = r.Host[:len(r.Host)-len(":" + serverPortHTTP)] + ":" + serverPortHTTPS
} else {
r.Host = r.Host[:len(r.Host)-len(":" + serverPortHTTP)]
}
http.Redirect(w, r, "https://"+r.Host+r.URL.String(), http.StatusMovedPermanently)
}))
if err != nil {
utils.Fatal("Listening to HTTP (Red)", err)
}
})()
http.Redirect(w, r, "https://"+r.Host+r.URL.String(), http.StatusMovedPermanently)
}))
if err != nil {
utils.Fatal("Listening to HTTP (Redirecting to HTTPS)", err)
}
})()
utils.Log("Listening to HTTP on :" + serverPortHTTP)
utils.Log("Listening to HTTPS on :" + serverPortHTTPS)
utils.Log("Listening to HTTP on :" + serverPortHTTP)
utils.Log("Listening to HTTPS on :" + serverPortHTTPS)
utils.IsHTTPS = true
utils.IsHTTPS = true
tlsConf := tlsconfig.NewServerTLSConfig(tlsconfig.TLSModeServerStrict)
if(config.HTTPConfig.HTTPSCertificateMode == utils.HTTPSCertModeList["LETSENCRYPT"]) {
tlsConf.GetCertificate = certReloader.GetCertificateFunc()
} else {
cert, errCert := tls.X509KeyPair(([]byte)(tlsCert), ([]byte)(tlsKey))
if errCert != nil {
utils.Fatal("Getting Certificate pair", errCert)
}
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{cert},
// Other options
}
// check if Docker overwrite Hostname
serverHostname := utils.GetMainConfig().HTTPConfig.Hostname
if os.Getenv("HOSTNAME") != "" {
serverHostname = os.Getenv("HOSTNAME")
}
server := http.Server{
TLSConfig: tlsConfig,
Addr: serverHostname + ":" + serverPortHTTPS,
ReadTimeout: 0,
ReadHeaderTimeout: 10 * time.Second,
WriteTimeout: 0,
IdleTimeout: 30 * time.Second,
Handler: router,
DisableGeneralOptionsHandler: true,
}
tlsConf.Certificates = []tls.Certificate{cert}
}
server := http.Server{
TLSConfig: tlsConf,
Addr: serverHostname + ":" + serverPortHTTPS,
ReadTimeout: 0,
ReadHeaderTimeout: 10 * time.Second,
WriteTimeout: 0,
IdleTimeout: 30 * time.Second,
Handler: router,
DisableGeneralOptionsHandler: true,
}
// start https server
err := server.ListenAndServeTLS("", "")
// start https server
errServ := server.ListenAndServeTLS("", "")
if err != nil {
utils.Fatal("Listening to HTTPS", err)
}
if errServ != nil {
utils.Fatal("Listening to HTTPS", errServ)
}
}
func tokenMiddleware(next http.Handler) http.Handler {
@ -127,13 +142,13 @@ func StartServer() {
serverPortHTTP = config.HTTPPort
serverPortHTTPS = config.HTTPSPort
var tlsCert = config.TLSCert
var tlsKey= config.TLSKey
configJson, _ := json.MarshalIndent(config, "", " ")
utils.Debug("Configuration" + (string)(configJson))
if((tlsCert == "" || tlsKey == "") && config.GenerateMissingTLSCert) {
var tlsCert = config.TLSCert
var tlsKey= config.TLSKey
if((tlsCert == "" || tlsKey == "") && config.HTTPSCertificateMode == utils.HTTPSCertModeList["SELFSIGNED"]) {
utils.Log("Generating new TLS certificate")
pub, priv := utils.GenerateRSAWebCertificates()
@ -184,7 +199,6 @@ func StartServer() {
srapi.HandleFunc("/api/servapps/{container}/secure", docker.SecureContainerRoute)
srapi.HandleFunc("/api/servapps", docker.ContainersRoute)
// srapi.Use(utils.AcceptHeader("*/*"))
srapi.Use(tokenMiddleware)
srapi.Use(utils.CORSHeader(utils.GetMainConfig().HTTPConfig.Hostname))
srapi.Use(utils.MiddlewareTimeout(20 * time.Second))
@ -209,11 +223,12 @@ func StartServer() {
router = proxy.BuildFromConfig(router, config.ProxyConfig)
if tlsCert != "" && tlsKey != "" {
if ((config.HTTPSCertificateMode == utils.HTTPSCertModeList["SELFSIGNED"] || config.HTTPSCertificateMode == utils.HTTPSCertModeList["PROVIDED"]) &&
tlsCert != "" && tlsKey != "") || (config.HTTPSCertificateMode == utils.HTTPSCertModeList["LETSENCRYPT"]) {
utils.Log("TLS certificate exist, starting HTTPS servers and redirecting HTTP to HTTPS")
startHTTPSServer(router, tlsCert, tlsKey)
} else {
utils.Log("TLS certificate does not exist, starting HTTP server only")
utils.Log("TLS certificates do not exists or are disabled, starting HTTP server only")
startHTTPServer(router)
}
}

View File

@ -18,7 +18,7 @@ func main() {
docker.DockerListenEvents()
// docker.BootstrapAllContainersFromTags()
docker.BootstrapAllContainersFromTags()
StartServer()
}

View File

@ -34,6 +34,15 @@ var ProxyModeList = map[string]string{
"PROXY": "PROXY",
"SPA": "SPA",
"STATIC": "STATIC",
"SERVAPP": "SERVAPP",
"REDIRECT": "REDIRECT",
}
var HTTPSCertModeList = map[string]string{
"DISABLED": "DISABLED",
"PROVIDED": "PROVIDED",
"SELFSIGNED": "SELFSIGNED",
"LETSENCRYPT": "LETSENCRYPT",
}
type FileStats struct {
@ -72,12 +81,13 @@ type HTTPConfig struct {
TLSKey string
AuthPrivateKey string
AuthPublicKey string
GenerateMissingTLSCert bool
GenerateMissingAuthCert bool
HTTPSCertificateMode string
HTTPPort string
HTTPSPort string
ProxyConfig ProxyConfig
Hostname string
SSLEmail string
}
type ProxyConfig struct {

View File

@ -17,7 +17,7 @@ var IsHTTPS = false
var DefaultConfig = Config{
LoggingLevel: "INFO",
HTTPConfig: HTTPConfig{
GenerateMissingTLSCert: true,
HTTPSCertificateMode: "DISABLED",
GenerateMissingAuthCert: true,
HTTPPort: "80",
HTTPSPort: "443",
@ -95,7 +95,7 @@ func LoadBaseMainConfig(config Config){
MainConfig.HTTPConfig.Hostname = os.Getenv("COSMOS_HOSTNAME")
}
if os.Getenv("COSMOS_GENERATE_MISSING_TLS_CERT") != "" {
MainConfig.HTTPConfig.GenerateMissingTLSCert = os.Getenv("COSMOS_GENERATE_MISSING_TLS_CERT") == "true"
MainConfig.HTTPConfig.HTTPSCertificateMode = os.Getenv("COSMOS_HTTPSCertificateMode")
}
if os.Getenv("COSMOS_GENERATE_MISSING_AUTH_CERT") != "" {
MainConfig.HTTPConfig.GenerateMissingAuthCert = os.Getenv("COSMOS_GENERATE_MISSING_AUTH_CERT") == "true"
@ -266,4 +266,17 @@ func AdminOrItselfOnly(w http.ResponseWriter, req *http.Request, nickname string
}
return nil
}
func GetAllHostnames() []string {
hostnames := []string{
GetMainConfig().HTTPConfig.Hostname,
}
proxies := GetMainConfig().HTTPConfig.ProxyConfig.Routes
for _, proxy := range proxies {
if proxy.UseHost {
hostnames = append(hostnames, proxy.Host)
}
}
return hostnames
}