diff --git a/cmd/system_update.go b/cmd/system_update.go
index db79e9d..057cef0 100644
--- a/cmd/system_update.go
+++ b/cmd/system_update.go
@@ -103,7 +103,7 @@ func (si systemupdate) Run(context wisski_distillery.Context) error {
// create the docker network
// TODO: Use docker API for this
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!
ctx := component.InstallationContext{
diff --git a/internal/component/control/control.env b/internal/component/control/control.env
index bfd1823..2b65aa7 100644
--- a/internal/component/control/control.env
+++ b/internal/component/control/control.env
@@ -1,10 +1,10 @@
-VIRTUAL_HOST=${VIRTUAL_HOST}
-
-LETSENCRYPT_HOST=${LETSENCRYPT_HOST}
-LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL}
+HOST_RULE=${HOST_RULE}
CONFIG_PATH=${CONFIG_PATH}
DEPLOY_ROOT=${DEPLOY_ROOT}
GLOBAL_AUTHORIZED_KEYS_FILE=${GLOBAL_AUTHORIZED_KEYS_FILE}
SELF_OVERRIDES_FILE=${SELF_OVERRIDES_FILE}
-SELF_RESOLVER_BLOCK_FILE=${SELF_RESOLVER_BLOCK_FILE}
\ No newline at end of file
+SELF_RESOLVER_BLOCK_FILE=${SELF_RESOLVER_BLOCK_FILE}
+
+DOCKER_NETWORK_NAME=${DOCKER_NETWORK_NAME}
+HTTPS_ENABLED=${HTTPS_ENABLED}
\ No newline at end of file
diff --git a/internal/component/control/control.go b/internal/component/control/control.go
index 1d2700a..64198f2 100644
--- a/internal/component/control/control.go
+++ b/internal/component/control/control.go
@@ -34,9 +34,9 @@ func (control *Control) Stack(env environment.Environment) component.StackWithRe
EnvPath: "control.env",
EnvContext: map[string]string{
- "VIRTUAL_HOST": control.Config.DefaultHost(),
- "LETSENCRYPT_HOST": control.Config.DefaultSSLHost(),
- "LETSENCRYPT_EMAIL": control.Config.CertbotEmail,
+ "DOCKER_NETWORK_NAME": control.Config.DockerNetworkName,
+ "HOST_RULE": control.Config.DefaultHostRule(),
+ "HTTPS_ENABLED": control.Config.HTTPSEnabledEnv(),
"CONFIG_PATH": control.Config.ConfigPath,
"DEPLOY_ROOT": control.Config.DeployRoot,
diff --git a/internal/component/control/control/docker-compose.yml b/internal/component/control/control/docker-compose.yml
index c95fe95..83c31ed 100644
--- a/internal/component/control/control/docker-compose.yml
+++ b/internal/component/control/control/docker-compose.yml
@@ -5,15 +5,20 @@ services:
build: .
restart: always
environment:
- # port and hostname for this image to use
- VIRTUAL_HOST: ${VIRTUAL_HOST}
- VIRTUAL_PORT: 8888
-
CONFIG_PATH: ${CONFIG_PATH}
-
- # optional letsencrypt email
- LETSENCRYPT_HOST: ${LETSENCRYPT_HOST}
- LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL}
+ labels:
+
+ - "traefik.enable=True"
+ - "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:
# TODO: Mount docker socket properly!
@@ -26,5 +31,5 @@ services:
networks:
default:
- name: distillery
+ name: ${DOCKER_NETWORK_NAME}
external: true
diff --git a/internal/component/info/html/index.html b/internal/component/info/html/index.html
index 57a2854..bb9fcbb 100644
--- a/internal/component/info/html/index.html
+++ b/internal/component/info/html/index.html
@@ -10,6 +10,7 @@
Domain: {{.Config.DefaultDomain}}
Legacy Domain(s): {{.Config.SelfExtraDomains}}
HTTPS Email: {{.Config.CertbotEmail}}
+ Docker Network Name: {{.Config.DockerNetworkName}}
Homepage Redirect:{{.Config.SelfRedirect}}
diff --git a/internal/component/instances/instances/barrel.env b/internal/component/instances/instances/barrel.env
index 9d93502..fbc862e 100644
--- a/internal/component/instances/instances/barrel.env
+++ b/internal/component/instances/instances/barrel.env
@@ -1,10 +1,9 @@
DATA_PATH=${DATA_PATH}
RUNTIME_DIR=${RUNTIME_DIR}
+GLOBAL_AUTHORIZED_KEYS_FILE=${GLOBAL_AUTHORIZED_KEYS_FILE}
SLUG=${SLUG}
VIRTUAL_HOST=${VIRTUAL_HOST}
+DOCKER_NETWORK_NAME=${DOCKER_NETWORK_NAME}
-LETSENCRYPT_HOST=${LETSENCRYPT_HOST}
-LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL}
-
-GLOBAL_AUTHORIZED_KEYS_FILE=${GLOBAL_AUTHORIZED_KEYS_FILE}
\ No newline at end of file
+HTTPS_ENABLED=${HTTPS_ENABLED}
\ No newline at end of file
diff --git a/internal/component/instances/instances/barrel/docker-compose.yml b/internal/component/instances/instances/barrel/docker-compose.yml
index 04dddab..43f109e 100644
--- a/internal/component/instances/instances/barrel/docker-compose.yml
+++ b/internal/component/instances/instances/barrel/docker-compose.yml
@@ -5,19 +5,19 @@ services:
build: .
restart: always
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
labels:
- 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.slug=${SLUG}"
+ - "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:
@@ -29,5 +29,5 @@ services:
networks:
default:
- name: distillery
+ name: ${DOCKER_NETWORK_NAME}
external: true
diff --git a/internal/component/instances/instances/reserve.env b/internal/component/instances/instances/reserve.env
index cd4d7da..b72c195 100644
--- a/internal/component/instances/instances/reserve.env
+++ b/internal/component/instances/instances/reserve.env
@@ -1,4 +1,5 @@
+SLUG=${SLUG}
VIRTUAL_HOST=${VIRTUAL_HOST}
-LETSENCRYPT_HOST=${LETSENCRYPT_HOST}
-LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL}
\ No newline at end of file
+DOCKER_NETWORK_NAME=${DOCKER_NETWORK_NAME}
+HTTPS_ENABLED=${HTTPS_ENABLED}
diff --git a/internal/component/instances/instances/reserve/docker-compose.yml b/internal/component/instances/instances/reserve/docker-compose.yml
index 666aa3f..acb2e42 100644
--- a/internal/component/instances/instances/reserve/docker-compose.yml
+++ b/internal/component/instances/instances/reserve/docker-compose.yml
@@ -4,23 +4,24 @@ services:
static:
image: tkw01536/gostatic
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:
- 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:
- ./index.html:/srv/http/index.html:ro
networks:
default:
- name: distillery
+ name: ${DOCKER_NETWORK_NAME}
external: true
diff --git a/internal/component/instances/wisski_stack.go b/internal/component/instances/wisski_stack.go
index 48f7bbf..cf5812c 100644
--- a/internal/component/instances/wisski_stack.go
+++ b/internal/component/instances/wisski_stack.go
@@ -25,14 +25,13 @@ func (wisski *WissKI) Barrel() component.StackWithResources {
EnvPath: filepath.Join("instances", "barrel.env"),
EnvContext: map[string]string{
- "DATA_PATH": filepath.Join(wisski.FilesystemBase, "data"),
+ "DOCKER_NETWORK_NAME": wisski.instances.Config.DockerNetworkName,
- "SLUG": wisski.Slug,
- "VIRTUAL_HOST": wisski.Domain(),
-
- "LETSENCRYPT_HOST": wisski.instances.Config.IfHttps(wisski.Domain()),
- "LETSENCRYPT_EMAIL": wisski.instances.Config.IfHttps(wisski.instances.Config.CertbotEmail),
+ "SLUG": wisski.Slug,
+ "VIRTUAL_HOST": wisski.Domain(),
+ "HTTPS_ENABLED": wisski.instances.Config.HTTPSEnabledEnv(),
+ "DATA_PATH": filepath.Join(wisski.FilesystemBase, "data"),
"RUNTIME_DIR": wisski.instances.Config.RuntimeDir(),
"GLOBAL_AUTHORIZED_KEYS_FILE": wisski.instances.Config.GlobalAuthorizedKeysFile,
},
@@ -109,10 +108,11 @@ func (wisski *WissKI) Reserve() component.StackWithResources {
EnvPath: filepath.Join("instances", "reserve.env"),
EnvContext: map[string]string{
- "VIRTUAL_HOST": wisski.Domain(),
+ "DOCKER_NETWORK_NAME": wisski.instances.Config.DockerNetworkName,
- "LETSENCRYPT_HOST": wisski.instances.Config.IfHttps(wisski.Domain()),
- "LETSENCRYPT_EMAIL": wisski.instances.Config.IfHttps(wisski.instances.Config.CertbotEmail),
+ "SLUG": wisski.Slug,
+ "VIRTUAL_HOST": wisski.Domain(),
+ "HTTPS_ENABLED": wisski.instances.Config.HTTPSEnabledEnv(),
},
}
}
diff --git a/internal/component/sql/sql.env b/internal/component/sql/sql.env
new file mode 100644
index 0000000..3089c4c
--- /dev/null
+++ b/internal/component/sql/sql.env
@@ -0,0 +1,2 @@
+DOCKER_NETWORK_NAME=${DOCKER_NETWORK_NAME}
+HTTPS_ENABLED=${HTTPS_ENABLED}
diff --git a/internal/component/sql/sql.go b/internal/component/sql/sql.go
index 199aaf8..acbcbf4 100644
--- a/internal/component/sql/sql.go
+++ b/internal/component/sql/sql.go
@@ -35,6 +35,7 @@ func (*SQL) Context(parent component.InstallationContext) component.Installation
}
//go:embed all:sql
+//go:embed sql.env
var resources embed.FS
func (sql *SQL) Stack(env environment.Environment) component.StackWithResources {
@@ -42,6 +43,12 @@ func (sql *SQL) Stack(env environment.Environment) component.StackWithResources
Resources: resources,
ContextPath: "sql",
+ EnvPath: "sql.env",
+ EnvContext: map[string]string{
+ "DOCKER_NETWORK_NAME": sql.Config.DockerNetworkName,
+ "HTTPS_ENABLED": sql.Config.HTTPSEnabledEnv(),
+ },
+
MakeDirsPerm: environment.DefaultDirPerm,
MakeDirs: []string{
"data",
diff --git a/internal/component/sql/sql/docker-compose.yml b/internal/component/sql/sql/docker-compose.yml
index a40cc82..5ffb0a5 100644
--- a/internal/component/sql/sql/docker-compose.yml
+++ b/internal/component/sql/sql/docker-compose.yml
@@ -7,6 +7,8 @@ services:
- "./data/:/var/lib/mysql"
ports:
- 127.0.0.1:3306:3306
+ labels:
+ - "eu.wiss-ki.barrel.distillery=${DOCKER_NETWORK_NAME}"
environment:
# This combination of environment variables will configure a passwordless root user
# 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.
ports:
- 127.0.0.1:8080:80
+ labels:
+ - "eu.wiss-ki.barrel.distillery=${DOCKER_NETWORK_NAME}"
depends_on:
- sql
restart: always
@@ -31,5 +35,5 @@ services:
networks:
default:
- name: distillery
+ name: ${DOCKER_NETWORK_NAME}
external: true
diff --git a/internal/component/ssh/ssh.env b/internal/component/ssh/ssh.env
new file mode 100644
index 0000000..131c6ab
--- /dev/null
+++ b/internal/component/ssh/ssh.env
@@ -0,0 +1 @@
+DOCKER_NETWORK_NAME=${DOCKER_NETWORK_NAME}
diff --git a/internal/component/ssh/ssh.go b/internal/component/ssh/ssh.go
index acd7ca6..0c07a0b 100644
--- a/internal/component/ssh/ssh.go
+++ b/internal/component/ssh/ssh.go
@@ -25,11 +25,17 @@ func (SSH) Context(parent component.InstallationContext) component.InstallationC
}
//go:embed all:ssh
+//go:embed ssh.env
var resources embed.FS
func (ssh *SSH) Stack(env environment.Environment) component.StackWithResources {
return component.MakeStack(ssh, env, component.StackWithResources{
Resources: resources,
ContextPath: "ssh",
+
+ EnvPath: "ssh.env",
+ EnvContext: map[string]string{
+ "DOCKER_NETWORK_NAME": ssh.Config.DockerNetworkName,
+ },
})
}
diff --git a/internal/component/ssh/ssh/docker-compose.yml b/internal/component/ssh/ssh/docker-compose.yml
index 7e7eb36..3566f74 100644
--- a/internal/component/ssh/ssh/docker-compose.yml
+++ b/internal/component/ssh/ssh/docker-compose.yml
@@ -9,9 +9,12 @@ services:
volumes:
- './data/keys:/keys'
- '/var/run/docker.sock:/var/run/docker.sock:ro'
+ labels:
+ - "eu.wiss-ki.barrel.distillery=${DOCKER_NETWORK_NAME}"
restart: always
networks:
default:
- name: distillery
+ name: ${DOCKER_NETWORK_NAME}
external: true
+
diff --git a/internal/component/stack.go b/internal/component/stack.go
index 931977b..932051d 100644
--- a/internal/component/stack.go
+++ b/internal/component/stack.go
@@ -204,10 +204,11 @@ type StackWithResources struct {
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
- 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
@@ -287,7 +288,7 @@ func (is StackWithResources) Install(io stream.IOStream, context InstallationCon
dst := filepath.Join(is.Dir, name)
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
}
}
diff --git a/internal/component/triplestore/triplestore.env b/internal/component/triplestore/triplestore.env
new file mode 100644
index 0000000..131c6ab
--- /dev/null
+++ b/internal/component/triplestore/triplestore.env
@@ -0,0 +1 @@
+DOCKER_NETWORK_NAME=${DOCKER_NETWORK_NAME}
diff --git a/internal/component/triplestore/triplestore.go b/internal/component/triplestore/triplestore.go
index 57b6e73..bb52708 100644
--- a/internal/component/triplestore/triplestore.go
+++ b/internal/component/triplestore/triplestore.go
@@ -32,6 +32,7 @@ func (Triplestore) Context(parent component.InstallationContext) component.Insta
}
//go:embed all:triplestore
+//go:embed triplestore.env
var resources embed.FS
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?
+ EnvPath: "triplestore.env",
+ EnvContext: map[string]string{
+ "DOCKER_NETWORK_NAME": ts.Config.DockerNetworkName,
+ },
+
MakeDirs: []string{
filepath.Join("data", "data"),
filepath.Join("data", "work"),
diff --git a/internal/component/triplestore/triplestore/docker-compose.yml b/internal/component/triplestore/triplestore/docker-compose.yml
index e1f2198..5f70431 100644
--- a/internal/component/triplestore/triplestore/docker-compose.yml
+++ b/internal/component/triplestore/triplestore/docker-compose.yml
@@ -13,10 +13,12 @@ services:
# Use 1GB of heap space
environment:
GDB_HEAP_SIZE: 16G
+ labels:
+ - "eu.wiss-ki.barrel.distillery=${DOCKER_NETWORK_NAME}"
restart: always
networks:
default:
- name: distillery
+ name: ${DOCKER_NETWORK_NAME}
external: true
\ No newline at end of file
diff --git a/internal/component/web/web-http.env b/internal/component/web/web-http.env
deleted file mode 100644
index 1eed846..0000000
--- a/internal/component/web/web-http.env
+++ /dev/null
@@ -1,2 +0,0 @@
-DEFAULT_HOST=${DEFAULT_HOST}
-HTTPS_METHOD=nohttps
\ No newline at end of file
diff --git a/internal/component/web/web-http/docker-compose.yml b/internal/component/web/web-http/docker-compose.yml
index f4c2113..774f692 100644
--- a/internal/component/web/web-http/docker-compose.yml
+++ b/internal/component/web/web-http/docker-compose.yml
@@ -1,30 +1,27 @@
version: "3.7"
services:
- nginx-proxy:
- image: ghcr.io/nginx-proxy/nginx-proxy:alpine
- environment:
- - DEFAULT_HOST=${DEFAULT_HOST}
- - HTTPS_METHOD=${HTTPS_METHOD}
+ reverse-proxy:
+ image: docker.io/library/traefik:v2.9
+ command:
+ - "--providers.docker"
+ - "--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:
- "80:80"
+ # - "127.0.0.1:8888:8080"
volumes:
- - "vhost:/etc/nginx/vhost.d"
- - "./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"
+ - "/var/run/docker.sock:/var/run/docker.sock"
restart: always
networks:
- default
-volumes:
- vhost:
- html:
- htpasswd:
-
networks:
default:
- name: distillery
+ name: ${DOCKER_NETWORK_NAME}
external: true
diff --git a/internal/component/web/web-http/global.conf b/internal/component/web/web-http/global.conf
deleted file mode 100644
index 2f73621..0000000
--- a/internal/component/web/web-http/global.conf
+++ /dev/null
@@ -1,4 +0,0 @@
-# Nginx Configuration File
-# These should match with distillery/resources/compose/barrel/conf/wisski.ini.
-
-client_max_body_size 1000m;
diff --git a/internal/component/web/web-http/proxy.conf b/internal/component/web/web-http/proxy.conf
deleted file mode 100644
index 59fec40..0000000
--- a/internal/component/web/web-http/proxy.conf
+++ /dev/null
@@ -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;
diff --git a/internal/component/web/web-https.env b/internal/component/web/web-https.env
deleted file mode 100644
index 00e84d1..0000000
--- a/internal/component/web/web-https.env
+++ /dev/null
@@ -1,2 +0,0 @@
-DEFAULT_HOST=${DEFAULT_HOST}
-HTTPS_METHOD=redirect
\ No newline at end of file
diff --git a/internal/component/web/web-https/docker-compose.yml b/internal/component/web/web-https/docker-compose.yml
index b11d520..7965e05 100644
--- a/internal/component/web/web-https/docker-compose.yml
+++ b/internal/component/web/web-https/docker-compose.yml
@@ -1,52 +1,41 @@
version: "3.7"
services:
- nginx-proxy:
- image: ghcr.io/nginx-proxy/nginx-proxy:alpine
- environment:
- - DEFAULT_HOST=${DEFAULT_HOST}
- - HTTPS_METHOD=${HTTPS_METHOD}
+ reverse-proxy:
+ image: docker.io/library/traefik:v2.9
+ command:
+ - "--providers.docker"
+
+ - "--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:
- "80:80"
- "443:443"
+ # - "127.0.0.1:8888:8080"
volumes:
- - "vhost:/etc/nginx/vhost.d"
- - "./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"
- - "certs:/etc/nginx/certs"
- labels:
- com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: true
+ - "/var/run/docker.sock:/var/run/docker.sock"
+ - "./acme.json:/acme.json"
restart: always
networks:
- 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:
default:
- name: distillery
+ name: ${DOCKER_NETWORK_NAME}
external: true
diff --git a/internal/component/web/web-https/global.conf b/internal/component/web/web-https/global.conf
deleted file mode 100644
index 2f73621..0000000
--- a/internal/component/web/web-https/global.conf
+++ /dev/null
@@ -1,4 +0,0 @@
-# Nginx Configuration File
-# These should match with distillery/resources/compose/barrel/conf/wisski.ini.
-
-client_max_body_size 1000m;
diff --git a/internal/component/web/web-https/proxy.conf b/internal/component/web/web-https/proxy.conf
deleted file mode 100644
index 59fec40..0000000
--- a/internal/component/web/web-https/proxy.conf
+++ /dev/null
@@ -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;
diff --git a/internal/component/web/web.env b/internal/component/web/web.env
new file mode 100644
index 0000000..33613c0
--- /dev/null
+++ b/internal/component/web/web.env
@@ -0,0 +1,2 @@
+DOCKER_NETWORK_NAME=${DOCKER_NETWORK_NAME}
+CERT_EMAIL=${CERT_EMAIL}
\ No newline at end of file
diff --git a/internal/component/web/web.go b/internal/component/web/web.go
index 7b90a9e..32754c0 100644
--- a/internal/component/web/web.go
+++ b/internal/component/web/web.go
@@ -37,33 +37,37 @@ func (web Web) Stack(env environment.Environment) component.StackWithResources {
}
//go:embed all:web-https
-//go:embed web-https.env
+//go:embed web.env
var httpsResources embed.FS
func (web *Web) stackHTTPS(env environment.Environment) component.StackWithResources {
return component.MakeStack(web, env, component.StackWithResources{
Resources: httpsResources,
ContextPath: "web-https",
- EnvPath: "web-https.env",
+ EnvPath: "web.env",
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 web-http.env
+//go:embed web.env
var httpResources embed.FS
func (web *Web) stackHTTP(env environment.Environment) component.StackWithResources {
return component.MakeStack(web, env, component.StackWithResources{
Resources: httpResources,
ContextPath: "web-http",
- EnvPath: "web-http.env",
+ EnvPath: "web.env",
EnvContext: map[string]string{
- "DEFAULT_HOST": web.Config.DefaultDomain,
+ "DOCKER_NETWORK_NAME": web.Config.DockerNetworkName,
+ "CERT_EMAIL": web.Config.CertbotEmail,
},
})
}
diff --git a/internal/config/config.go b/internal/config/config.go
index 2acf4b1..1167bf5 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -83,6 +83,9 @@ type Config struct {
DisAdminUser string `env:"DIS_ADMIN_USER" default:"admin" 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 string
}
diff --git a/internal/config/config_template b/internal/config/config_template
index 12b8c67..d3c22f0 100644
--- a/internal/config/config_template
+++ b/internal/config/config_template
@@ -2,6 +2,9 @@
# On top of this all real-system space will be created under this directory.
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.
# 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.
diff --git a/internal/config/domains.go b/internal/config/domains.go
index f7c637a..05234b0 100644
--- a/internal/config/domains.go
+++ b/internal/config/domains.go
@@ -1,7 +1,10 @@
package config
import (
+ "fmt"
"strings"
+
+ "github.com/tkw1536/goprogram/lib/collection"
)
// This file contains domain related derived configuration values.
@@ -11,6 +14,22 @@ func (cfg Config) HTTPSEnabled() bool {
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.
func (cfg Config) IfHttps(value string) string {
if !cfg.HTTPSEnabled() {
@@ -19,27 +38,17 @@ func (cfg Config) IfHttps(value string) string {
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].
-// Domain names are concatinated with commas.
-func (cfg Config) DefaultHost() string {
- var builder strings.Builder
-
- builder.WriteString(cfg.DefaultDomain)
- for _, domain := range cfg.SelfExtraDomains {
- builder.WriteRune(',')
- builder.WriteString(domain)
- }
-
- return builder.String()
+func (cfg Config) DefaultHostRule() string {
+ return cfg.HostRule(append([]string{cfg.DefaultDomain}, cfg.SelfExtraDomains...)...)
}
// 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.
-func (cfg Config) DefaultSSLHost() string {
- return cfg.IfHttps(cfg.DefaultHost())
+func (cfg Config) xDefaultSSLHost() string {
+ panic("not implemented")
}
// SlugFromHost returns the slug belonging to the appropriate host.'
diff --git a/internal/config/template.go b/internal/config/template.go
index 1c85f1e..ffbc11a 100644
--- a/internal/config/template.go
+++ b/internal/config/template.go
@@ -28,6 +28,7 @@ type Template struct {
MysqlAdminPassword string `env:"MYSQL_ADMIN_PASSWORD"`
DisAdminUsername string `env:"DIS_ADMIN_USER"`
DisAdminPassword string `env:"DIS_ADMIN_PASSWORD"`
+ DockerNetworkName string `env:"DOCKER_NETWORK_NAME"`
}
// 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
}
diff --git a/pkg/fsx/touch.go b/pkg/fsx/touch.go
index aefa694..412f2d7 100644
--- a/pkg/fsx/touch.go
+++ b/pkg/fsx/touch.go
@@ -1,6 +1,7 @@
package fsx
import (
+ "io/fs"
"time"
"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 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)
switch {
case environment.IsNotExist(err):
- f, err := env.Create(path, environment.DefaultFilePerm)
+ f, err := env.Create(path, perm)
if err != nil {
return err
}
diff --git a/pkg/unpack/template.go b/pkg/unpack/template.go
index 2e7f86b..98e17d2 100644
--- a/pkg/unpack/template.go
+++ b/pkg/unpack/template.go
@@ -177,7 +177,7 @@ parseloop:
// Check if there were missing template keys.
// If so, we sort them and return an appropriate error.
if len(missingKeys) != 0 {
- keys := maps.Keys(unusedKeys)
+ keys := maps.Keys(missingKeys)
slices.Sort(keys)
return MissingTemplateKeyError{
Keys: keys,