diff options
-rwxr-xr-x | deploy/build-image.sh | 55 | ||||
-rw-r--r-- | deploy/headers_secure.conf | 10 | ||||
-rw-r--r-- | deploy/headers_static.conf | 3 | ||||
-rw-r--r-- | deploy/nginx.conf | 60 | ||||
-rw-r--r-- | deploy/www.yaml | 131 |
5 files changed, 259 insertions, 0 deletions
diff --git a/deploy/build-image.sh b/deploy/build-image.sh new file mode 100755 index 0000000..4d576dd --- /dev/null +++ b/deploy/build-image.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +set -eu + +(cd .. && make clean build) + +ret=0; output=$(buildah images adyxax/alpine &>/dev/null) || ret=$? +if [ $ret != 0 ]; then + ALPINE_LATEST=$(curl --silent https://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/x86_64/ | + perl -lane '$latest = $1 if $_ =~ /^<a href="(alpine-minirootfs-\d+\.\d+\.\d+-x86_64\.tar\.gz)">/; END {print $latest}' + ) + if [ ! -e "./${ALPINE_LATEST}" ]; then + echo "Fetching ${ALPINE_LATEST}..." + curl --silent https://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/x86_64/${ALPINE_LATEST} \ + --output ./${ALPINE_LATEST} + fi + + ctr=$(buildah from scratch) + buildah add $ctr ${ALPINE_LATEST} / + buildah run $ctr /bin/sh -c 'apk add --no-cache pcre sqlite-libs' + buildah commit $ctr adyxax/alpine +else + ctr=$(buildah from adyxax/alpine) + #buildah run $ctr /bin/sh -c 'apk upgrade --no-cache' +fi + +ret=0; buildah images adyxax/nginx &>/dev/null || ret=$? +if [ $ret != 0 ]; then + nginx=$(buildah from adyxax/alpine) + buildah run $nginx /bin/sh -c 'apk add --no-cache nginx' + buildah commit $nginx adyxax/nginx +else + nginx=$(buildah from adyxax/nginx) + #buildah run $nginx /bin/sh -c 'apk upgrade --no-cache' +fi + +buildah copy $nginx nginx.conf headers_secure.conf headers_static.conf /etc/nginx/ +buildah config \ + --author 'Julien Dessaux' \ + --cmd nginx \ + --port 80 \ + $nginx +buildah copy $nginx ../public /var/www/www.adyxax.org + +buildah commit $nginx adyxax/www +buildah rm $nginx + +ctr=$(buildah from scratch) +buildah copy $ctr ../search/search / +buildah config \ + --author 'Julien Dessaux' \ + --cmd /search \ + --port 8080 \ + $ctr +buildah commit $ctr adyxax/www-search +buildah rm $ctr diff --git a/deploy/headers_secure.conf b/deploy/headers_secure.conf new file mode 100644 index 0000000..71b52e1 --- /dev/null +++ b/deploy/headers_secure.conf @@ -0,0 +1,10 @@ +# A+ on https://securityheaders.io/ +add_header X-Frame-Options deny; +add_header X-XSS-Protection "1; mode=block"; +add_header X-Content-Type-Options nosniff; +add_header Referrer-Policy strict-origin; +add_header Cache-Control no-transform; +add_header Content-Security-Policy "script-src 'self'"; +add_header Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()"; +# 6 months HSTS pinning +add_header Strict-Transport-Security max-age=16000000; diff --git a/deploy/headers_static.conf b/deploy/headers_static.conf new file mode 100644 index 0000000..2b3f31d --- /dev/null +++ b/deploy/headers_static.conf @@ -0,0 +1,3 @@ +include headers_secure.conf; +# Infinite caching +add_header Cache-Control "public, max-age=31536000, immutable"; diff --git a/deploy/nginx.conf b/deploy/nginx.conf new file mode 100644 index 0000000..d4fe348 --- /dev/null +++ b/deploy/nginx.conf @@ -0,0 +1,60 @@ +user nginx; +worker_processes 1; +daemon off; + +events { + # The maximum number of simultaneous connections that can be opened by + # a worker process + worker_connections 1024; +} + +http { + # Includes mapping of file name extensions to MIME types of responses + # and defines the default type. + include /etc/nginx/mime.types; + default_type application/octet-stream; + + # Don't tell nginx version to the clients. Default is 'on'. + server_tokens off; + + # Specifies the maximum accepted body size of a client request, as + # indicated by the request header Content-Length. If the stated content + # length is greater than this size, then the client receives the HTTP + # error code 413. Set to 0 to disable. Default is '1m'. + client_max_body_size 1m; + + # Sendfile copies data between one FD and other from within the kernel, + # which is more efficient than read() + write(). Default is off. + sendfile on; + + # Causes nginx to attempt to send its HTTP response head in one packet, + # instead of using partial frames. Default is 'off'. + tcp_nopush on; + + # Enables or disables the use of the TCP_NODELAY option. The option is + # enabled when a connection is transitioned into the keep-alive state. + # Additionally, it is enabled on SSL connections, for unbuffered + # proxying, and for WebSocket proxying. + tcp_nodelay on; + + # Specifies the main log format. + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + server { + listen 80; + listen [::]:80; + server_name _; + root /var/www/www.adyxax.org/; + index index.html; + error_page 404 /404.html; + + location /static { + include /etc/nginx/headers_static.conf; + } + location / { + include headers_secure.conf; + add_header Cache-Control "private, max-age=0, must-revalidate, no-transform"; + } + } +} diff --git a/deploy/www.yaml b/deploy/www.yaml new file mode 100644 index 0000000..70abe42 --- /dev/null +++ b/deploy/www.yaml @@ -0,0 +1,131 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: www +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: www + name: www + labels: + app: www +spec: + replicas: 1 + strategy: + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + type: RollingUpdate + selector: + matchLabels: + app: www + template: + metadata: + labels: + app: www + spec: + containers: + - name: www + image: quay.io/adyxax/www:2021111202 + ports: + - containerPort: 80 + readinessProbe: + httpGet: + path: '/' + port: 80 + initialDelaySeconds: 1 + timeoutSeconds: 1 + livenessProbe: + httpGet: + path: '/' + port: 80 + initialDelaySeconds: 1 + timeoutSeconds: 1 + lifecycle: + preStop: + exec: + command: ["/bin/sh", "-c", "sleep 10"] + - name: search + image: quay.io/adyxax/www-search:2021111202 + ports: + - containerPort: 8080 + readinessProbe: + httpGet: + path: '/search/' + port: 8080 + initialDelaySeconds: 1 + timeoutSeconds: 1 + livenessProbe: + httpGet: + path: '/search/' + port: 8080 + initialDelaySeconds: 1 + timeoutSeconds: 1 + lifecycle: + preStop: + exec: + command: ["/bin/sh", "-c", "sleep 10"] +--- +apiVersion: v1 +kind: Service +metadata: + namespace: www + name: www +spec: + type: ClusterIP + selector: + app: www + ports: + - protocol: TCP + port: 80 + targetPort: 80 + name: www + - protocol: TCP + port: 8080 + targetPort: 8080 + name: search +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + namespace: www + name: www +spec: + ingressClassName: nginx + tls: + - secretName: wildcard-adyxax-org + rules: + - host: www.adyxax.org + http: + paths: + - path: '/' + pathType: Prefix + backend: + service: + name: www + port: + number: 80 + - path: '/search' + pathType: Prefix + backend: + service: + name: www + port: + number: 8080 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + namespace: www + name: redirects + annotations: + nginx.ingress.kubernetes.io/permanent-redirect: https://www.adyxax.org/ + nginx.ingress.kubernetes.io/permanent-redirect-code: "308" +spec: + ingressClassName: nginx + tls: + - secretName: wildcard-adyxax-org + rules: + - host: adyxax.org + - host: wiki.adyxax.org |