Move to Traefik
This commit is contained in:
parent
bf57c0d5a6
commit
471ccbadc5
36 changed files with 200 additions and 190 deletions
|
|
@ -103,7 +103,7 @@ func (si systemupdate) Run(context wisski_distillery.Context) error {
|
||||||
// create the docker network
|
// create the docker network
|
||||||
// TODO: Use docker API for this
|
// TODO: Use docker API for this
|
||||||
logging.LogMessage(context.IOStream, "Updating Docker Configuration")
|
logging.LogMessage(context.IOStream, "Updating Docker Configuration")
|
||||||
si.mustExec(context, "", "docker", "network", "create", "distillery")
|
si.mustExec(context, "", "docker", "network", "create", dis.Config.DockerNetworkName)
|
||||||
|
|
||||||
// install and update the various stacks!
|
// install and update the various stacks!
|
||||||
ctx := component.InstallationContext{
|
ctx := component.InstallationContext{
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
VIRTUAL_HOST=${VIRTUAL_HOST}
|
HOST_RULE=${HOST_RULE}
|
||||||
|
|
||||||
LETSENCRYPT_HOST=${LETSENCRYPT_HOST}
|
|
||||||
LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL}
|
|
||||||
|
|
||||||
CONFIG_PATH=${CONFIG_PATH}
|
CONFIG_PATH=${CONFIG_PATH}
|
||||||
DEPLOY_ROOT=${DEPLOY_ROOT}
|
DEPLOY_ROOT=${DEPLOY_ROOT}
|
||||||
GLOBAL_AUTHORIZED_KEYS_FILE=${GLOBAL_AUTHORIZED_KEYS_FILE}
|
GLOBAL_AUTHORIZED_KEYS_FILE=${GLOBAL_AUTHORIZED_KEYS_FILE}
|
||||||
SELF_OVERRIDES_FILE=${SELF_OVERRIDES_FILE}
|
SELF_OVERRIDES_FILE=${SELF_OVERRIDES_FILE}
|
||||||
SELF_RESOLVER_BLOCK_FILE=${SELF_RESOLVER_BLOCK_FILE}
|
SELF_RESOLVER_BLOCK_FILE=${SELF_RESOLVER_BLOCK_FILE}
|
||||||
|
|
||||||
|
DOCKER_NETWORK_NAME=${DOCKER_NETWORK_NAME}
|
||||||
|
HTTPS_ENABLED=${HTTPS_ENABLED}
|
||||||
|
|
@ -34,9 +34,9 @@ func (control *Control) Stack(env environment.Environment) component.StackWithRe
|
||||||
EnvPath: "control.env",
|
EnvPath: "control.env",
|
||||||
|
|
||||||
EnvContext: map[string]string{
|
EnvContext: map[string]string{
|
||||||
"VIRTUAL_HOST": control.Config.DefaultHost(),
|
"DOCKER_NETWORK_NAME": control.Config.DockerNetworkName,
|
||||||
"LETSENCRYPT_HOST": control.Config.DefaultSSLHost(),
|
"HOST_RULE": control.Config.DefaultHostRule(),
|
||||||
"LETSENCRYPT_EMAIL": control.Config.CertbotEmail,
|
"HTTPS_ENABLED": control.Config.HTTPSEnabledEnv(),
|
||||||
|
|
||||||
"CONFIG_PATH": control.Config.ConfigPath,
|
"CONFIG_PATH": control.Config.ConfigPath,
|
||||||
"DEPLOY_ROOT": control.Config.DeployRoot,
|
"DEPLOY_ROOT": control.Config.DeployRoot,
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,20 @@ services:
|
||||||
build: .
|
build: .
|
||||||
restart: always
|
restart: always
|
||||||
environment:
|
environment:
|
||||||
# port and hostname for this image to use
|
|
||||||
VIRTUAL_HOST: ${VIRTUAL_HOST}
|
|
||||||
VIRTUAL_PORT: 8888
|
|
||||||
|
|
||||||
CONFIG_PATH: ${CONFIG_PATH}
|
CONFIG_PATH: ${CONFIG_PATH}
|
||||||
|
labels:
|
||||||
# optional letsencrypt email
|
|
||||||
LETSENCRYPT_HOST: ${LETSENCRYPT_HOST}
|
- "traefik.enable=True"
|
||||||
LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL}
|
- "eu.wiss-ki.barrel.distillery=${DOCKER_NETWORK_NAME}"
|
||||||
|
- "traefik.http.routers.control.rule=${HOST_RULE}"
|
||||||
|
|
||||||
|
- "traefik.http.routers.fallback.rule=HostRegexp(`{catchall:.*}`)"
|
||||||
|
- "traefik.http.routers.fallback.priority=1"
|
||||||
|
|
||||||
|
- "traefik.http.routers.control.tls=${HTTPS_ENABLED}"
|
||||||
|
- "traefik.http.routers.control.tls.certresolver=distillery"
|
||||||
|
- "traefik.http.services.control.loadbalancer.server.port=8888"
|
||||||
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
# TODO: Mount docker socket properly!
|
# TODO: Mount docker socket properly!
|
||||||
|
|
@ -26,5 +31,5 @@ services:
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
name: distillery
|
name: ${DOCKER_NETWORK_NAME}
|
||||||
external: true
|
external: true
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
<b>Domain:</b> <code>{{.Config.DefaultDomain}}</code> <br />
|
<b>Domain:</b> <code>{{.Config.DefaultDomain}}</code> <br />
|
||||||
<b>Legacy Domain(s):</b> <code>{{.Config.SelfExtraDomains}}</code><br />
|
<b>Legacy Domain(s):</b> <code>{{.Config.SelfExtraDomains}}</code><br />
|
||||||
<b>HTTPS Email:</b> <code>{{.Config.CertbotEmail}}</code><br />
|
<b>HTTPS Email:</b> <code>{{.Config.CertbotEmail}}</code><br />
|
||||||
|
<b>Docker Network Name:</b> <code>{{.Config.DockerNetworkName}}</code><br />
|
||||||
<hr />
|
<hr />
|
||||||
<b>Homepage Redirect:</b><a href="{{.Config.SelfRedirect}}" target="_blank" rel="noopener noreferrer">{{.Config.SelfRedirect}}</a><br />
|
<b>Homepage Redirect:</b><a href="{{.Config.SelfRedirect}}" target="_blank" rel="noopener noreferrer">{{.Config.SelfRedirect}}</a><br />
|
||||||
<hr />
|
<hr />
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
DATA_PATH=${DATA_PATH}
|
DATA_PATH=${DATA_PATH}
|
||||||
RUNTIME_DIR=${RUNTIME_DIR}
|
RUNTIME_DIR=${RUNTIME_DIR}
|
||||||
|
GLOBAL_AUTHORIZED_KEYS_FILE=${GLOBAL_AUTHORIZED_KEYS_FILE}
|
||||||
|
|
||||||
SLUG=${SLUG}
|
SLUG=${SLUG}
|
||||||
VIRTUAL_HOST=${VIRTUAL_HOST}
|
VIRTUAL_HOST=${VIRTUAL_HOST}
|
||||||
|
DOCKER_NETWORK_NAME=${DOCKER_NETWORK_NAME}
|
||||||
|
|
||||||
LETSENCRYPT_HOST=${LETSENCRYPT_HOST}
|
HTTPS_ENABLED=${HTTPS_ENABLED}
|
||||||
LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL}
|
|
||||||
|
|
||||||
GLOBAL_AUTHORIZED_KEYS_FILE=${GLOBAL_AUTHORIZED_KEYS_FILE}
|
|
||||||
|
|
@ -5,19 +5,19 @@ services:
|
||||||
build: .
|
build: .
|
||||||
restart: always
|
restart: always
|
||||||
hostname: ${VIRTUAL_HOST}.wisski
|
hostname: ${VIRTUAL_HOST}.wisski
|
||||||
environment:
|
|
||||||
# port and hostname for this image to use
|
|
||||||
VIRTUAL_HOST: ${VIRTUAL_HOST}
|
|
||||||
VIRTUAL_PORT: 8080
|
|
||||||
|
|
||||||
# optional letsencrypt email
|
|
||||||
LETSENCRYPT_HOST: ${LETSENCRYPT_HOST}
|
|
||||||
LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL}
|
|
||||||
|
|
||||||
# label it with the current slug
|
# label it with the current slug
|
||||||
labels:
|
labels:
|
||||||
eu.wiss-ki.barrel.slug: ${SLUG}
|
- "eu.wiss-ki.barrel.slug=${SLUG}"
|
||||||
eu.wiss-ki.barrel.authfile: /var/www/.ssh/authorized_keys,/var/www/.ssh/global_authorized_keys
|
- "eu.wiss-ki.barrel.authfile:=/var/www/.ssh/authorized_keys,/var/www/.ssh/global_authorized_keys"
|
||||||
|
|
||||||
|
- "traefik.enable=True"
|
||||||
|
- "eu.wiss-ki.barrel.distillery=${DOCKER_NETWORK_NAME}"
|
||||||
|
|
||||||
|
- "traefik.http.routers.wisski_${SLUG}.rule=Host(`${VIRTUAL_HOST}`)"
|
||||||
|
- "traefik.http.routers.wisski_${SLUG}.tls=${HTTPS_ENABLED}"
|
||||||
|
- "traefik.http.routers.wisski_${SLUG}.tls.certresolver=distillery"
|
||||||
|
- "traefik.http.services.wisski_${SLUG}.loadbalancer.server.port=8080"
|
||||||
|
|
||||||
# volumes that are mounted
|
# volumes that are mounted
|
||||||
volumes:
|
volumes:
|
||||||
|
|
@ -29,5 +29,5 @@ services:
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
name: distillery
|
name: ${DOCKER_NETWORK_NAME}
|
||||||
external: true
|
external: true
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
|
SLUG=${SLUG}
|
||||||
VIRTUAL_HOST=${VIRTUAL_HOST}
|
VIRTUAL_HOST=${VIRTUAL_HOST}
|
||||||
|
|
||||||
LETSENCRYPT_HOST=${LETSENCRYPT_HOST}
|
DOCKER_NETWORK_NAME=${DOCKER_NETWORK_NAME}
|
||||||
LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL}
|
HTTPS_ENABLED=${HTTPS_ENABLED}
|
||||||
|
|
|
||||||
|
|
@ -4,23 +4,24 @@ services:
|
||||||
static:
|
static:
|
||||||
image: tkw01536/gostatic
|
image: tkw01536/gostatic
|
||||||
restart: always
|
restart: always
|
||||||
environment:
|
|
||||||
# port and hostname for this image to use
|
|
||||||
VIRTUAL_HOST: ${VIRTUAL_HOST}
|
|
||||||
VIRTUAL_PORT: 8043
|
|
||||||
|
|
||||||
# optional letsencrypt email
|
|
||||||
LETSENCRYPT_HOST: ${LETSENCRYPT_HOST}
|
|
||||||
LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL}
|
|
||||||
|
|
||||||
ports:
|
ports:
|
||||||
- 8043
|
- 8043
|
||||||
|
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=True"
|
||||||
|
- "eu.wiss-ki.barrel.distillery=${DOCKER_NETWORK_NAME}"
|
||||||
|
|
||||||
|
- "traefik.http.routers.reserve_${SLUG}.rule=Host(`${VIRTUAL_HOST}`)"
|
||||||
|
- "traefik.http.routers.reserve_${SLUG}.tls=${HTTPS_ENABLED}"
|
||||||
|
- "traefik.http.routers.reserve_${SLUG}.tls.certresolver=distillery"
|
||||||
|
- "traefik.http.services.reserve_${SLUG}.loadbalancer.server.port=8043"
|
||||||
|
|
||||||
|
|
||||||
# volumes that are mounted
|
# volumes that are mounted
|
||||||
volumes:
|
volumes:
|
||||||
- ./index.html:/srv/http/index.html:ro
|
- ./index.html:/srv/http/index.html:ro
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
name: distillery
|
name: ${DOCKER_NETWORK_NAME}
|
||||||
external: true
|
external: true
|
||||||
|
|
|
||||||
|
|
@ -25,14 +25,13 @@ func (wisski *WissKI) Barrel() component.StackWithResources {
|
||||||
EnvPath: filepath.Join("instances", "barrel.env"),
|
EnvPath: filepath.Join("instances", "barrel.env"),
|
||||||
|
|
||||||
EnvContext: map[string]string{
|
EnvContext: map[string]string{
|
||||||
"DATA_PATH": filepath.Join(wisski.FilesystemBase, "data"),
|
"DOCKER_NETWORK_NAME": wisski.instances.Config.DockerNetworkName,
|
||||||
|
|
||||||
"SLUG": wisski.Slug,
|
"SLUG": wisski.Slug,
|
||||||
"VIRTUAL_HOST": wisski.Domain(),
|
"VIRTUAL_HOST": wisski.Domain(),
|
||||||
|
"HTTPS_ENABLED": wisski.instances.Config.HTTPSEnabledEnv(),
|
||||||
"LETSENCRYPT_HOST": wisski.instances.Config.IfHttps(wisski.Domain()),
|
|
||||||
"LETSENCRYPT_EMAIL": wisski.instances.Config.IfHttps(wisski.instances.Config.CertbotEmail),
|
|
||||||
|
|
||||||
|
"DATA_PATH": filepath.Join(wisski.FilesystemBase, "data"),
|
||||||
"RUNTIME_DIR": wisski.instances.Config.RuntimeDir(),
|
"RUNTIME_DIR": wisski.instances.Config.RuntimeDir(),
|
||||||
"GLOBAL_AUTHORIZED_KEYS_FILE": wisski.instances.Config.GlobalAuthorizedKeysFile,
|
"GLOBAL_AUTHORIZED_KEYS_FILE": wisski.instances.Config.GlobalAuthorizedKeysFile,
|
||||||
},
|
},
|
||||||
|
|
@ -109,10 +108,11 @@ func (wisski *WissKI) Reserve() component.StackWithResources {
|
||||||
EnvPath: filepath.Join("instances", "reserve.env"),
|
EnvPath: filepath.Join("instances", "reserve.env"),
|
||||||
|
|
||||||
EnvContext: map[string]string{
|
EnvContext: map[string]string{
|
||||||
"VIRTUAL_HOST": wisski.Domain(),
|
"DOCKER_NETWORK_NAME": wisski.instances.Config.DockerNetworkName,
|
||||||
|
|
||||||
"LETSENCRYPT_HOST": wisski.instances.Config.IfHttps(wisski.Domain()),
|
"SLUG": wisski.Slug,
|
||||||
"LETSENCRYPT_EMAIL": wisski.instances.Config.IfHttps(wisski.instances.Config.CertbotEmail),
|
"VIRTUAL_HOST": wisski.Domain(),
|
||||||
|
"HTTPS_ENABLED": wisski.instances.Config.HTTPSEnabledEnv(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
internal/component/sql/sql.env
Normal file
2
internal/component/sql/sql.env
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
DOCKER_NETWORK_NAME=${DOCKER_NETWORK_NAME}
|
||||||
|
HTTPS_ENABLED=${HTTPS_ENABLED}
|
||||||
|
|
@ -35,6 +35,7 @@ func (*SQL) Context(parent component.InstallationContext) component.Installation
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:embed all:sql
|
//go:embed all:sql
|
||||||
|
//go:embed sql.env
|
||||||
var resources embed.FS
|
var resources embed.FS
|
||||||
|
|
||||||
func (sql *SQL) Stack(env environment.Environment) component.StackWithResources {
|
func (sql *SQL) Stack(env environment.Environment) component.StackWithResources {
|
||||||
|
|
@ -42,6 +43,12 @@ func (sql *SQL) Stack(env environment.Environment) component.StackWithResources
|
||||||
Resources: resources,
|
Resources: resources,
|
||||||
ContextPath: "sql",
|
ContextPath: "sql",
|
||||||
|
|
||||||
|
EnvPath: "sql.env",
|
||||||
|
EnvContext: map[string]string{
|
||||||
|
"DOCKER_NETWORK_NAME": sql.Config.DockerNetworkName,
|
||||||
|
"HTTPS_ENABLED": sql.Config.HTTPSEnabledEnv(),
|
||||||
|
},
|
||||||
|
|
||||||
MakeDirsPerm: environment.DefaultDirPerm,
|
MakeDirsPerm: environment.DefaultDirPerm,
|
||||||
MakeDirs: []string{
|
MakeDirs: []string{
|
||||||
"data",
|
"data",
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ services:
|
||||||
- "./data/:/var/lib/mysql"
|
- "./data/:/var/lib/mysql"
|
||||||
ports:
|
ports:
|
||||||
- 127.0.0.1:3306:3306
|
- 127.0.0.1:3306:3306
|
||||||
|
labels:
|
||||||
|
- "eu.wiss-ki.barrel.distillery=${DOCKER_NETWORK_NAME}"
|
||||||
environment:
|
environment:
|
||||||
# This combination of environment variables will configure a passwordless root user
|
# This combination of environment variables will configure a passwordless root user
|
||||||
# that can only connect to the container from 'localhost'.
|
# that can only connect to the container from 'localhost'.
|
||||||
|
|
@ -24,6 +26,8 @@ services:
|
||||||
# By default no admin account is created, so initial shell access to make one is needed.
|
# By default no admin account is created, so initial shell access to make one is needed.
|
||||||
ports:
|
ports:
|
||||||
- 127.0.0.1:8080:80
|
- 127.0.0.1:8080:80
|
||||||
|
labels:
|
||||||
|
- "eu.wiss-ki.barrel.distillery=${DOCKER_NETWORK_NAME}"
|
||||||
depends_on:
|
depends_on:
|
||||||
- sql
|
- sql
|
||||||
restart: always
|
restart: always
|
||||||
|
|
@ -31,5 +35,5 @@ services:
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
name: distillery
|
name: ${DOCKER_NETWORK_NAME}
|
||||||
external: true
|
external: true
|
||||||
|
|
|
||||||
1
internal/component/ssh/ssh.env
Normal file
1
internal/component/ssh/ssh.env
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
DOCKER_NETWORK_NAME=${DOCKER_NETWORK_NAME}
|
||||||
|
|
@ -25,11 +25,17 @@ func (SSH) Context(parent component.InstallationContext) component.InstallationC
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:embed all:ssh
|
//go:embed all:ssh
|
||||||
|
//go:embed ssh.env
|
||||||
var resources embed.FS
|
var resources embed.FS
|
||||||
|
|
||||||
func (ssh *SSH) Stack(env environment.Environment) component.StackWithResources {
|
func (ssh *SSH) Stack(env environment.Environment) component.StackWithResources {
|
||||||
return component.MakeStack(ssh, env, component.StackWithResources{
|
return component.MakeStack(ssh, env, component.StackWithResources{
|
||||||
Resources: resources,
|
Resources: resources,
|
||||||
ContextPath: "ssh",
|
ContextPath: "ssh",
|
||||||
|
|
||||||
|
EnvPath: "ssh.env",
|
||||||
|
EnvContext: map[string]string{
|
||||||
|
"DOCKER_NETWORK_NAME": ssh.Config.DockerNetworkName,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,12 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- './data/keys:/keys'
|
- './data/keys:/keys'
|
||||||
- '/var/run/docker.sock:/var/run/docker.sock:ro'
|
- '/var/run/docker.sock:/var/run/docker.sock:ro'
|
||||||
|
labels:
|
||||||
|
- "eu.wiss-ki.barrel.distillery=${DOCKER_NETWORK_NAME}"
|
||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
name: distillery
|
name: ${DOCKER_NETWORK_NAME}
|
||||||
external: true
|
external: true
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -204,10 +204,11 @@ type StackWithResources struct {
|
||||||
|
|
||||||
CopyContextFiles []string // Files to copy from the installation context
|
CopyContextFiles []string // Files to copy from the installation context
|
||||||
|
|
||||||
MakeDirsPerm fs.FileMode // permission for diretories, defaults to [environment.DefaultDirCreate]
|
MakeDirsPerm fs.FileMode // permission for dirctories, defaults to [environment.DefaultDirCreate]
|
||||||
MakeDirs []string // directories to ensure that exist
|
MakeDirs []string // directories to ensure that exist
|
||||||
|
|
||||||
TouchFiles []string // Files to 'touch', i.e. ensure that exist; guaranteed to be run after MakeDirs
|
TouchFilesPerm fs.FileMode // permission for new files to touch, defaults to [environment.DefaultFileCreate]
|
||||||
|
TouchFiles []string // Files to 'touch', i.e. ensure that exist; guaranteed to be run after MakeDirs
|
||||||
}
|
}
|
||||||
|
|
||||||
// InstallationContext is a context to install data in
|
// InstallationContext is a context to install data in
|
||||||
|
|
@ -287,7 +288,7 @@ func (is StackWithResources) Install(io stream.IOStream, context InstallationCon
|
||||||
dst := filepath.Join(is.Dir, name)
|
dst := filepath.Join(is.Dir, name)
|
||||||
|
|
||||||
io.Printf("[touch] %s\n", dst)
|
io.Printf("[touch] %s\n", dst)
|
||||||
if err := fsx.Touch(env, dst); err != nil {
|
if err := fsx.Touch(env, dst, is.TouchFilesPerm); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
internal/component/triplestore/triplestore.env
Normal file
1
internal/component/triplestore/triplestore.env
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
DOCKER_NETWORK_NAME=${DOCKER_NETWORK_NAME}
|
||||||
|
|
@ -32,6 +32,7 @@ func (Triplestore) Context(parent component.InstallationContext) component.Insta
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:embed all:triplestore
|
//go:embed all:triplestore
|
||||||
|
//go:embed triplestore.env
|
||||||
var resources embed.FS
|
var resources embed.FS
|
||||||
|
|
||||||
func (ts *Triplestore) Stack(env environment.Environment) component.StackWithResources {
|
func (ts *Triplestore) Stack(env environment.Environment) component.StackWithResources {
|
||||||
|
|
@ -41,6 +42,11 @@ func (ts *Triplestore) Stack(env environment.Environment) component.StackWithRes
|
||||||
|
|
||||||
CopyContextFiles: []string{"graphdb.zip"}, // TODO: Move into constant?
|
CopyContextFiles: []string{"graphdb.zip"}, // TODO: Move into constant?
|
||||||
|
|
||||||
|
EnvPath: "triplestore.env",
|
||||||
|
EnvContext: map[string]string{
|
||||||
|
"DOCKER_NETWORK_NAME": ts.Config.DockerNetworkName,
|
||||||
|
},
|
||||||
|
|
||||||
MakeDirs: []string{
|
MakeDirs: []string{
|
||||||
filepath.Join("data", "data"),
|
filepath.Join("data", "data"),
|
||||||
filepath.Join("data", "work"),
|
filepath.Join("data", "work"),
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,12 @@ services:
|
||||||
# Use 1GB of heap space
|
# Use 1GB of heap space
|
||||||
environment:
|
environment:
|
||||||
GDB_HEAP_SIZE: 16G
|
GDB_HEAP_SIZE: 16G
|
||||||
|
labels:
|
||||||
|
- "eu.wiss-ki.barrel.distillery=${DOCKER_NETWORK_NAME}"
|
||||||
|
|
||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
name: distillery
|
name: ${DOCKER_NETWORK_NAME}
|
||||||
external: true
|
external: true
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
DEFAULT_HOST=${DEFAULT_HOST}
|
|
||||||
HTTPS_METHOD=nohttps
|
|
||||||
|
|
@ -1,30 +1,27 @@
|
||||||
version: "3.7"
|
version: "3.7"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
nginx-proxy:
|
reverse-proxy:
|
||||||
image: ghcr.io/nginx-proxy/nginx-proxy:alpine
|
image: docker.io/library/traefik:v2.9
|
||||||
environment:
|
command:
|
||||||
- DEFAULT_HOST=${DEFAULT_HOST}
|
- "--providers.docker"
|
||||||
- HTTPS_METHOD=${HTTPS_METHOD}
|
- "--providers.docker.exposedByDefault=false"
|
||||||
|
- "--providers.docker.network=${DOCKER_NETWORK_NAME}"
|
||||||
|
- "--providers.docker.constraints=Label(`eu.wiss-ki.barrel.distillery`,`${DOCKER_NETWORK_NAME}`)"
|
||||||
|
- "--entrypoints.web.address=:80"
|
||||||
|
|
||||||
|
## for debugging purposes, the following can be enabled.
|
||||||
|
# - "--api.insecure=true"
|
||||||
ports:
|
ports:
|
||||||
- "80:80"
|
- "80:80"
|
||||||
|
# - "127.0.0.1:8888:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- "vhost:/etc/nginx/vhost.d"
|
- "/var/run/docker.sock:/var/run/docker.sock"
|
||||||
- "./global.conf:/etc/nginx/conf.d/global.conf:ro"
|
|
||||||
- "./proxy.conf:/etc/nginx/proxy.conf:ro"
|
|
||||||
- "htpasswd:/etc/nginx/htpasswd"
|
|
||||||
- "html:/usr/share/nginx/html"
|
|
||||||
- "/var/run/docker.sock:/tmp/docker.sock:ro"
|
|
||||||
restart: always
|
restart: always
|
||||||
networks:
|
networks:
|
||||||
- default
|
- default
|
||||||
|
|
||||||
volumes:
|
|
||||||
vhost:
|
|
||||||
html:
|
|
||||||
htpasswd:
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
name: distillery
|
name: ${DOCKER_NETWORK_NAME}
|
||||||
external: true
|
external: true
|
||||||
|
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
# Nginx Configuration File
|
|
||||||
# These should match with distillery/resources/compose/barrel/conf/wisski.ini.
|
|
||||||
|
|
||||||
client_max_body_size 1000m;
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
# HTTP 1.1 support
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_buffering off;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection $proxy_connection;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
|
|
||||||
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
|
|
||||||
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
|
|
||||||
|
|
||||||
# Mitigate httpoxy attack (see README for details)
|
|
||||||
proxy_set_header Proxy "";
|
|
||||||
|
|
||||||
# Timeouts for the proxy connection - in sync with the appropriate max_execution time.
|
|
||||||
proxy_connect_timeout 3000s;
|
|
||||||
proxy_read_timeout 3000s;
|
|
||||||
proxy_send_timeout 3000s;
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
DEFAULT_HOST=${DEFAULT_HOST}
|
|
||||||
HTTPS_METHOD=redirect
|
|
||||||
|
|
@ -1,52 +1,41 @@
|
||||||
version: "3.7"
|
version: "3.7"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
nginx-proxy:
|
reverse-proxy:
|
||||||
image: ghcr.io/nginx-proxy/nginx-proxy:alpine
|
image: docker.io/library/traefik:v2.9
|
||||||
environment:
|
command:
|
||||||
- DEFAULT_HOST=${DEFAULT_HOST}
|
- "--providers.docker"
|
||||||
- HTTPS_METHOD=${HTTPS_METHOD}
|
|
||||||
|
- "--providers.docker.exposedByDefault=false"
|
||||||
|
- "--providers.docker.network=${DOCKER_NETWORK_NAME}"
|
||||||
|
- "--providers.docker.constraints=Label(`eu.wiss-ki.barrel.distillery`,`${DOCKER_NETWORK_NAME}`)"
|
||||||
|
|
||||||
|
- "--entrypoints.web.address=:80"
|
||||||
|
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
|
||||||
|
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
|
||||||
|
- "--entrypoints.websecure.address=:443"
|
||||||
|
|
||||||
|
- "--certificatesresolvers.distillery.acme.httpchallenge=true"
|
||||||
|
- "--certificatesresolvers.distillery.acme.email=${CERT_EMAIL}"
|
||||||
|
- "--certificatesresolvers.distillery.acme.storage=/acme.json"
|
||||||
|
- "--certificatesresolvers.distillery.acme.httpchallenge.entrypoint=web"
|
||||||
|
|
||||||
|
## for debugging purposes, the following can be enabled.
|
||||||
|
# - "--api.insecure=true"
|
||||||
|
# - "--certificatesresolvers.distillery.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||||
|
|
||||||
ports:
|
ports:
|
||||||
- "80:80"
|
- "80:80"
|
||||||
- "443:443"
|
- "443:443"
|
||||||
|
# - "127.0.0.1:8888:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- "vhost:/etc/nginx/vhost.d"
|
- "/var/run/docker.sock:/var/run/docker.sock"
|
||||||
- "./global.conf:/etc/nginx/conf.d/global.conf:ro"
|
- "./acme.json:/acme.json"
|
||||||
- "./proxy.conf:/etc/nginx/proxy.conf:ro"
|
|
||||||
- "htpasswd:/etc/nginx/htpasswd"
|
|
||||||
- "html:/usr/share/nginx/html"
|
|
||||||
- "/var/run/docker.sock:/tmp/docker.sock:ro"
|
|
||||||
- "certs:/etc/nginx/certs"
|
|
||||||
labels:
|
|
||||||
com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: true
|
|
||||||
restart: always
|
restart: always
|
||||||
networks:
|
networks:
|
||||||
- default
|
- default
|
||||||
|
|
||||||
letsencrypt-nginx-proxy-companion:
|
|
||||||
image: docker.io/nginxproxy/acme-companion:latest
|
|
||||||
volumes:
|
|
||||||
- "/var/run/docker.sock:/var/run/docker.sock:ro"
|
|
||||||
- "htpasswd:/etc/nginx/htpasswd"
|
|
||||||
- "vhost:/etc/nginx/vhost.d"
|
|
||||||
- "html:/usr/share/nginx/html"
|
|
||||||
- "/var/run/docker.sock:/tmp/docker.sock:ro"
|
|
||||||
- "certs:/etc/nginx/certs"
|
|
||||||
- "acme:/etc/acme.sh"
|
|
||||||
restart: always
|
|
||||||
networks:
|
|
||||||
- default
|
|
||||||
depends_on:
|
|
||||||
- nginx-proxy
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
acme:
|
|
||||||
vhost:
|
|
||||||
html:
|
|
||||||
certs:
|
|
||||||
htpasswd:
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
name: distillery
|
name: ${DOCKER_NETWORK_NAME}
|
||||||
external: true
|
external: true
|
||||||
|
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
# Nginx Configuration File
|
|
||||||
# These should match with distillery/resources/compose/barrel/conf/wisski.ini.
|
|
||||||
|
|
||||||
client_max_body_size 1000m;
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
# HTTP 1.1 support
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_buffering off;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection $proxy_connection;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
|
|
||||||
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
|
|
||||||
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
|
|
||||||
|
|
||||||
# Mitigate httpoxy attack (see README for details)
|
|
||||||
proxy_set_header Proxy "";
|
|
||||||
|
|
||||||
# Timeouts for the proxy connection - in sync with the appropriate max_execution time.
|
|
||||||
proxy_connect_timeout 3000s;
|
|
||||||
proxy_read_timeout 3000s;
|
|
||||||
proxy_send_timeout 3000s;
|
|
||||||
2
internal/component/web/web.env
Normal file
2
internal/component/web/web.env
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
DOCKER_NETWORK_NAME=${DOCKER_NETWORK_NAME}
|
||||||
|
CERT_EMAIL=${CERT_EMAIL}
|
||||||
|
|
@ -37,33 +37,37 @@ func (web Web) Stack(env environment.Environment) component.StackWithResources {
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:embed all:web-https
|
//go:embed all:web-https
|
||||||
//go:embed web-https.env
|
//go:embed web.env
|
||||||
var httpsResources embed.FS
|
var httpsResources embed.FS
|
||||||
|
|
||||||
func (web *Web) stackHTTPS(env environment.Environment) component.StackWithResources {
|
func (web *Web) stackHTTPS(env environment.Environment) component.StackWithResources {
|
||||||
return component.MakeStack(web, env, component.StackWithResources{
|
return component.MakeStack(web, env, component.StackWithResources{
|
||||||
Resources: httpsResources,
|
Resources: httpsResources,
|
||||||
ContextPath: "web-https",
|
ContextPath: "web-https",
|
||||||
EnvPath: "web-https.env",
|
EnvPath: "web.env",
|
||||||
|
|
||||||
EnvContext: map[string]string{
|
EnvContext: map[string]string{
|
||||||
"DEFAULT_HOST": web.Config.DefaultDomain,
|
"DOCKER_NETWORK_NAME": web.Config.DockerNetworkName,
|
||||||
|
"CERT_EMAIL": web.Config.CertbotEmail,
|
||||||
},
|
},
|
||||||
|
TouchFilesPerm: 0600,
|
||||||
|
TouchFiles: []string{"acme.json"},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:embed all:web-http
|
//go:embed all:web-http
|
||||||
//go:embed web-http.env
|
//go:embed web.env
|
||||||
var httpResources embed.FS
|
var httpResources embed.FS
|
||||||
|
|
||||||
func (web *Web) stackHTTP(env environment.Environment) component.StackWithResources {
|
func (web *Web) stackHTTP(env environment.Environment) component.StackWithResources {
|
||||||
return component.MakeStack(web, env, component.StackWithResources{
|
return component.MakeStack(web, env, component.StackWithResources{
|
||||||
Resources: httpResources,
|
Resources: httpResources,
|
||||||
ContextPath: "web-http",
|
ContextPath: "web-http",
|
||||||
EnvPath: "web-http.env",
|
EnvPath: "web.env",
|
||||||
|
|
||||||
EnvContext: map[string]string{
|
EnvContext: map[string]string{
|
||||||
"DEFAULT_HOST": web.Config.DefaultDomain,
|
"DOCKER_NETWORK_NAME": web.Config.DockerNetworkName,
|
||||||
|
"CERT_EMAIL": web.Config.CertbotEmail,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,9 @@ type Config struct {
|
||||||
DisAdminUser string `env:"DIS_ADMIN_USER" default:"admin" parser:"nonempty"`
|
DisAdminUser string `env:"DIS_ADMIN_USER" default:"admin" parser:"nonempty"`
|
||||||
DisAdminPassword string `env:"DIS_ADMIN_PASSWORD" default:"" parser:"nonempty"`
|
DisAdminPassword string `env:"DIS_ADMIN_PASSWORD" default:"" parser:"nonempty"`
|
||||||
|
|
||||||
|
// name of docker network to use
|
||||||
|
DockerNetworkName string `env:"DOCKER_NETWORK_NAME" default:"distillery" parser:"nonempty"`
|
||||||
|
|
||||||
// ConfigPath is the path this configuration was loaded from (if any)
|
// ConfigPath is the path this configuration was loaded from (if any)
|
||||||
ConfigPath string
|
ConfigPath string
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,9 @@
|
||||||
# On top of this all real-system space will be created under this directory.
|
# On top of this all real-system space will be created under this directory.
|
||||||
DEPLOY_ROOT=${DEPLOY_ROOT}
|
DEPLOY_ROOT=${DEPLOY_ROOT}
|
||||||
|
|
||||||
|
# The name of the (global) docker network to run the distillery services in.
|
||||||
|
DOCKER_NETWORK_NAME=${DOCKER_NETWORK_NAME}
|
||||||
|
|
||||||
# Each created Drupal Instance corresponds to a single domain name.
|
# Each created Drupal Instance corresponds to a single domain name.
|
||||||
# These domain names should either be a complete domain name or a sub-domain of a default domain.
|
# These domain names should either be a complete domain name or a sub-domain of a default domain.
|
||||||
# This setting configures the default domain-name to create subdomains of.
|
# This setting configures the default domain-name to create subdomains of.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/tkw1536/goprogram/lib/collection"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This file contains domain related derived configuration values.
|
// This file contains domain related derived configuration values.
|
||||||
|
|
@ -11,6 +14,22 @@ func (cfg Config) HTTPSEnabled() bool {
|
||||||
return cfg.CertbotEmail != ""
|
return cfg.CertbotEmail != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HostRequirement returns a traefik rule for the given names
|
||||||
|
func (Config) HostRule(names ...string) string {
|
||||||
|
quoted := collection.MapSlice(names, func(name string) string {
|
||||||
|
return "`" + name + "`"
|
||||||
|
})
|
||||||
|
return fmt.Sprintf("Host(%s)", strings.Join(quoted, ","))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTPSEnabledEnv returns "true" if https is enabled, and "false" otherwise.
|
||||||
|
func (cfg Config) HTTPSEnabledEnv() string {
|
||||||
|
if cfg.HTTPSEnabled() {
|
||||||
|
return "true"
|
||||||
|
}
|
||||||
|
return "false"
|
||||||
|
}
|
||||||
|
|
||||||
// IfHttps returns value when the distillery has https enabled, and the empty string otherwise.
|
// IfHttps returns value when the distillery has https enabled, and the empty string otherwise.
|
||||||
func (cfg Config) IfHttps(value string) string {
|
func (cfg Config) IfHttps(value string) string {
|
||||||
if !cfg.HTTPSEnabled() {
|
if !cfg.HTTPSEnabled() {
|
||||||
|
|
@ -19,27 +38,17 @@ func (cfg Config) IfHttps(value string) string {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultHost returns the default hostname for the distillery.
|
// DefaultHostRule returns the default traefik hostname rule for this distillery.
|
||||||
//
|
|
||||||
// This consists of the [DefaultDomain] as well as [ExtraDomains].
|
// This consists of the [DefaultDomain] as well as [ExtraDomains].
|
||||||
// Domain names are concatinated with commas.
|
func (cfg Config) DefaultHostRule() string {
|
||||||
func (cfg Config) DefaultHost() string {
|
return cfg.HostRule(append([]string{cfg.DefaultDomain}, cfg.SelfExtraDomains...)...)
|
||||||
var builder strings.Builder
|
|
||||||
|
|
||||||
builder.WriteString(cfg.DefaultDomain)
|
|
||||||
for _, domain := range cfg.SelfExtraDomains {
|
|
||||||
builder.WriteRune(',')
|
|
||||||
builder.WriteString(domain)
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder.String()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultSSLHost returns the default hostname for the ssl version of the distillery.
|
// DefaultSSLHost returns the default hostname for the ssl version of the distillery.
|
||||||
//
|
//
|
||||||
// This is exactly [DefaultHost] when SSL is enabled, and the empty string otherwise.
|
// This is exactly [DefaultHost] when SSL is enabled, and the empty string otherwise.
|
||||||
func (cfg Config) DefaultSSLHost() string {
|
func (cfg Config) xDefaultSSLHost() string {
|
||||||
return cfg.IfHttps(cfg.DefaultHost())
|
panic("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
// SlugFromHost returns the slug belonging to the appropriate host.'
|
// SlugFromHost returns the slug belonging to the appropriate host.'
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ type Template struct {
|
||||||
MysqlAdminPassword string `env:"MYSQL_ADMIN_PASSWORD"`
|
MysqlAdminPassword string `env:"MYSQL_ADMIN_PASSWORD"`
|
||||||
DisAdminUsername string `env:"DIS_ADMIN_USER"`
|
DisAdminUsername string `env:"DIS_ADMIN_USER"`
|
||||||
DisAdminPassword string `env:"DIS_ADMIN_PASSWORD"`
|
DisAdminPassword string `env:"DIS_ADMIN_PASSWORD"`
|
||||||
|
DockerNetworkName string `env:"DOCKER_NETWORK_NAME"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDefaults sets defaults on the template
|
// SetDefaults sets defaults on the template
|
||||||
|
|
@ -85,6 +86,14 @@ func (tpl *Template) SetDefaults(env environment.Environment) (err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if tpl.DockerNetworkName == "" {
|
||||||
|
tpl.DockerNetworkName, err = password.Password(10)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tpl.DockerNetworkName = `distillery-` + tpl.DockerNetworkName
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package fsx
|
package fsx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/fs"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/FAU-CDI/wisski-distillery/pkg/environment"
|
"github.com/FAU-CDI/wisski-distillery/pkg/environment"
|
||||||
|
|
@ -11,11 +12,14 @@ import (
|
||||||
//
|
//
|
||||||
// If the file does not exist exists, it is created using [env.Create].
|
// If the file does not exist exists, it is created using [env.Create].
|
||||||
// If the file does exist, it's access and modification times are updated to the current time.
|
// If the file does exist, it's access and modification times are updated to the current time.
|
||||||
func Touch(env environment.Environment, path string) error {
|
func Touch(env environment.Environment, path string, perm fs.FileMode) error {
|
||||||
|
if perm == 0 {
|
||||||
|
perm = environment.DefaultFilePerm
|
||||||
|
}
|
||||||
_, err := env.Stat(path)
|
_, err := env.Stat(path)
|
||||||
switch {
|
switch {
|
||||||
case environment.IsNotExist(err):
|
case environment.IsNotExist(err):
|
||||||
f, err := env.Create(path, environment.DefaultFilePerm)
|
f, err := env.Create(path, perm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -177,7 +177,7 @@ parseloop:
|
||||||
// Check if there were missing template keys.
|
// Check if there were missing template keys.
|
||||||
// If so, we sort them and return an appropriate error.
|
// If so, we sort them and return an appropriate error.
|
||||||
if len(missingKeys) != 0 {
|
if len(missingKeys) != 0 {
|
||||||
keys := maps.Keys(unusedKeys)
|
keys := maps.Keys(missingKeys)
|
||||||
slices.Sort(keys)
|
slices.Sort(keys)
|
||||||
return MissingTemplateKeyError{
|
return MissingTemplateKeyError{
|
||||||
Keys: keys,
|
Keys: keys,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue