This commit is contained in:
2024-05-16 18:39:05 +02:00
parent 377b430669
commit fe68c68633
13 changed files with 1332 additions and 6 deletions

13
apps/wordpress/check.rhai Normal file
View File

@@ -0,0 +1,13 @@
const DOMAIN = config.domain;
fn check_domain() {
assert(have_namespace(`${global::DOMAIN}`), `There is no ${global::DOMAIN} namespace`);
}
fn check_authentik() {
assert(have_namespace(`${global::DOMAIN}-auth`), `There is no ${global::DOMAIN}-auth namespace`);
assert(have_install(`${global::DOMAIN}-auth`, "authentik"), `No authentik installation in ${global::DOMAIN}-auth`);
assert(have_secret(`${global::DOMAIN}-auth`, "authentik"), `No authentik secret in ${global::DOMAIN}-auth`);
}
fn pre_check() {
check_domain();
check_authentik();
}

29
apps/wordpress/common.tf Normal file
View File

@@ -0,0 +1,29 @@
locals {
core_labels = {
"app.kubernetes.io/name" = var.component
"app.kubernetes.io/instance" = var.instance
}
common_labels = merge({
"vynil.solidite.fr/owner-name" = var.instance
"vynil.solidite.fr/owner-namespace" = var.namespace
"vynil.solidite.fr/owner-category" = var.category
"vynil.solidite.fr/owner-component" = var.component
"app.kubernetes.io/managed-by" = "vynil"
},local.core_labels)
wp_labels = merge({
"app.kubernetes.io/componant" = var.component
},local.core_labels)
wp_all_labels = merge({
"app.kubernetes.io/componant" = var.component
},local.common_labels)
db_labels = merge({
"app.kubernetes.io/componant" = "database"
},local.common_labels)
secrets_labels = merge(local.common_labels, {
"app.kubernetes.io/component" = "backup-secret"
})
secret_labels = merge(local.secrets_labels, {
"k8up.io/backup" = "true"
})
}

104
apps/wordpress/database.tf Normal file
View File

@@ -0,0 +1,104 @@
resource "random_password" "mysql_root_pass" {
length = 32
special = false
}
resource "random_password" "mysql_comp_pass" {
length = 32
special = false
}
locals {
mysql_host = "${var.instance}-${var.component}-rw.${var.namespace}.svc"
mysql_username = "root"
mysql_password = random_password.mysql_root_pass.result
}
resource "kubectl_manifest" "mysql_root_pass" {
yaml_body = <<-EOF
apiVersion: v1
kind: Secret
metadata:
name: "${var.instance}-${var.component}-mysql-root"
labels: ${jsonencode(local.common_labels)}
namespace: ${var.namespace}
stringData:
password: "${random_password.mysql_root_pass.result}"
EOF
}
resource "kubectl_manifest" "ndb" {
yaml_body = <<-EOF
apiVersion: mysql.oracle.com/v1
kind: NdbCluster
metadata:
name: "${var.instance}-${var.component}"
labels: ${jsonencode(local.db_labels)}
namespace: ${var.namespace}
spec:
redundancyLevel: 1
dataNode:
nodeCount: 1
pvcSpec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
mysqlNode:
nodeCount: 1
rootPasswordSecretName: ${kubectl_manifest.mysql_root_pass.name}
myCnf: |
[mysqld]
default_storage_engine=NDBCLUSTER
EOF
}
resource "time_sleep" "wait_ndb_ready" {
depends_on = [kubectl_manifest.ndb]
create_duration = "180s"
}
resource "mysql_database" "component" {
depends_on = [ time_sleep.wait_ndb_ready, kubectl_manifest.ndb ]
name = var.component
}
resource "mysql_user" "component" {
depends_on = [ time_sleep.wait_ndb_ready, kubectl_manifest.ndb ]
user = var.component
host = "%.${module.service.default_definition.name}.${var.namespace}.%"
plaintext_password = random_password.mysql_comp_pass.result
}
resource "mysql_grant" "component" {
user = mysql_user.component.user
host = mysql_user.component.host
database = mysql_database.component.name
privileges = ["ALL"]
}
resource "kubectl_manifest" "pre_backup_pod_db" {
count = var.backups.enable?1:0
ignore_fields = ["metadata.annotations"]
yaml_body = <<-EOF
apiVersion: k8up.io/v1
kind: PreBackupPod
metadata:
name: "${var.instance}-${var.component}-db"
namespace: "${var.namespace}"
labels: ${jsonencode(local.secrets_labels)}
spec:
backupCommand: mysqldump --all-databases --password=$$MYSQL_PWD --host=${var.instance}-${var.component}-mysqld.${var.namespace}.svc --no-create-db --add-drop-table
pod:
spec:
containers:
- command:
- cat
env:
- name: MYSQL_PWD
valueFrom:
secretKeyRef:
key: password
name: "${kubectl_manifest.mysql_root_pass.name}"
image: "${var.images.mysql.registry}/${var.images.mysql.repository}:${var.images.mysql.tag}"
imagePullPolicy: "${var.images.mysql.pull_policy}"
name: secret
tty: true
serviceAccount: backup-secret
serviceAccountName: backup-secret
EOF
}

495
apps/wordpress/index.yaml Normal file
View File

@@ -0,0 +1,495 @@
---
apiVersion: vinyl.solidite.fr/v1beta1
kind: Component
category: apps
metadata:
name: wordpress
description: null
options:
app_group:
default: apps
examples:
- apps
type: string
backups:
default:
enable: false
endpoint: ''
key_id_key: s3-id
restic_key: bck-password
retention:
db: 30d
keepDaily: 14
keepMonthly: 12
keepWeekly: 6
keepYearly: 12
schedule:
backup: 10 3 * * *
check: 10 5 * * 1
db: 10 3 * * *
prune: 10 1 * * 0
secret_key: s3-secret
secret_name: backup-settings
use_barman: false
examples:
- enable: false
endpoint: ''
key_id_key: s3-id
restic_key: bck-password
retention:
db: 30d
keepDaily: 14
keepMonthly: 12
keepWeekly: 6
keepYearly: 12
schedule:
backup: 10 3 * * *
check: 10 5 * * 1
db: 10 3 * * *
prune: 10 1 * * 0
secret_key: s3-secret
secret_name: backup-settings
use_barman: false
properties:
enable:
default: false
type: boolean
endpoint:
default: ''
type: string
key_id_key:
default: s3-id
type: string
restic_key:
default: bck-password
type: string
retention:
default:
db: 30d
keepDaily: 14
keepMonthly: 12
keepWeekly: 6
keepYearly: 12
properties:
db:
default: 30d
type: string
keepDaily:
default: 14
type: integer
keepMonthly:
default: 12
type: integer
keepWeekly:
default: 6
type: integer
keepYearly:
default: 12
type: integer
type: object
schedule:
default:
backup: 10 3 * * *
check: 10 5 * * 1
db: 10 3 * * *
prune: 10 1 * * 0
properties:
backup:
default: 10 3 * * *
type: string
check:
default: 10 5 * * 1
type: string
db:
default: 10 3 * * *
type: string
prune:
default: 10 1 * * 0
type: string
type: object
secret_key:
default: s3-secret
type: string
secret_name:
default: backup-settings
type: string
use_barman:
default: false
type: boolean
type: object
domain:
default: your-company
examples:
- your-company
type: string
domain_name:
default: your-company.com
examples:
- your-company.com
type: string
hpa:
default:
avg-cpu: 50
max-replicas: 5
min-replicas: 1
examples:
- avg-cpu: 50
max-replicas: 5
min-replicas: 1
properties:
avg-cpu:
default: 50
type: integer
max-replicas:
default: 5
type: integer
min-replicas:
default: 1
type: integer
type: object
images:
default:
kubectl:
pull_policy: IfNotPresent
registry: docker.io
repository: sebt3/basic-toolbox-image
tag: 1.29.3
mysql:
pull_policy: IfNotPresent
registry: docker.io
repository: mysql
tag: 8.4.0-oraclelinux9
nginx:
pull_policy: IfNotPresent
registry: docker.io
repository: nginx
tag: alpine
redis:
pull_policy: IfNotPresent
registry: quay.io
repository: opstree/redis
tag: v7.0.12
redis_exporter:
pull_policy: IfNotPresent
registry: quay.io
repository: opstree/redis-exporter
tag: v1.44.0
wordpress:
pull_policy: IfNotPresent
registry: docker.io
repository: wordpress
tag: 6.5.3-php8.3-fpm
examples:
- kubectl:
pull_policy: IfNotPresent
registry: docker.io
repository: sebt3/basic-toolbox-image
tag: 1.29.3
mysql:
pull_policy: IfNotPresent
registry: docker.io
repository: mysql
tag: 8.4.0-oraclelinux9
nginx:
pull_policy: IfNotPresent
registry: docker.io
repository: nginx
tag: alpine
redis:
pull_policy: IfNotPresent
registry: quay.io
repository: opstree/redis
tag: v7.0.12
redis_exporter:
pull_policy: IfNotPresent
registry: quay.io
repository: opstree/redis-exporter
tag: v1.44.0
wordpress:
pull_policy: IfNotPresent
registry: docker.io
repository: wordpress
tag: 6.5.3-php8.3-fpm
properties:
kubectl:
default:
pull_policy: IfNotPresent
registry: docker.io
repository: sebt3/basic-toolbox-image
tag: 1.29.3
properties:
pull_policy:
default: IfNotPresent
enum:
- Always
- Never
- IfNotPresent
type: string
registry:
default: docker.io
type: string
repository:
default: sebt3/basic-toolbox-image
type: string
tag:
default: 1.29.3
type: string
type: object
mysql:
default:
pull_policy: IfNotPresent
registry: docker.io
repository: mysql
tag: 8.4.0-oraclelinux9
properties:
pull_policy:
default: IfNotPresent
enum:
- Always
- Never
- IfNotPresent
type: string
registry:
default: docker.io
type: string
repository:
default: mysql
type: string
tag:
default: 8.4.0-oraclelinux9
type: string
type: object
nginx:
default:
pull_policy: IfNotPresent
registry: docker.io
repository: nginx
tag: alpine
properties:
pull_policy:
default: IfNotPresent
enum:
- Always
- Never
- IfNotPresent
type: string
registry:
default: docker.io
type: string
repository:
default: nginx
type: string
tag:
default: alpine
type: string
type: object
redis:
default:
pull_policy: IfNotPresent
registry: quay.io
repository: opstree/redis
tag: v7.0.12
properties:
pull_policy:
default: IfNotPresent
enum:
- Always
- Never
- IfNotPresent
type: string
registry:
default: quay.io
type: string
repository:
default: opstree/redis
type: string
tag:
default: v7.0.12
type: string
type: object
redis_exporter:
default:
pull_policy: IfNotPresent
registry: quay.io
repository: opstree/redis-exporter
tag: v1.44.0
properties:
pull_policy:
default: IfNotPresent
enum:
- Always
- Never
- IfNotPresent
type: string
registry:
default: quay.io
type: string
repository:
default: opstree/redis-exporter
type: string
tag:
default: v1.44.0
type: string
type: object
wordpress:
default:
pull_policy: IfNotPresent
registry: docker.io
repository: wordpress
tag: 6.5.3-php8.3-fpm
properties:
pull_policy:
default: IfNotPresent
enum:
- Always
- Never
- IfNotPresent
type: string
registry:
default: docker.io
type: string
repository:
default: wordpress
type: string
tag:
default: 6.5.3-php8.3-fpm
type: string
type: object
type: object
ingress_class:
default: traefik
examples:
- traefik
type: string
issuer:
default: letsencrypt-prod
examples:
- letsencrypt-prod
type: string
ndb:
default:
replicas: 1
examples:
- replicas: 1
properties:
replicas:
default: 1
type: integer
type: object
redis:
default:
exporter:
enabled: true
examples:
- exporter:
enabled: true
properties:
exporter:
default:
enabled: true
properties:
enabled:
default: true
type: boolean
type: object
type: object
replicas:
default: 1
examples:
- 1
type: integer
storage:
default:
ndb:
size: 10Gi
redis:
size: 2Gi
volume:
accessMode: ReadWriteOnce
class: ''
maxSize: 100Gi
size: 10Gi
type: Filesystem
description: Configure this app storage
examples:
- ndb:
size: 10Gi
redis:
size: 2Gi
volume:
accessMode: ReadWriteOnce
class: ''
maxSize: 100Gi
size: 10Gi
type: Filesystem
properties:
ndb:
default:
size: 10Gi
properties:
size:
default: 10Gi
type: string
type: object
redis:
default:
size: 2Gi
properties:
size:
default: 2Gi
type: string
type: object
volume:
default:
accessMode: ReadWriteOnce
class: ''
maxSize: 100Gi
size: 10Gi
type: Filesystem
properties:
accessMode:
default: ReadWriteOnce
enum:
- ReadWriteOnce
- ReadOnlyMany
- ReadWriteMany
type: string
class:
default: ''
type: string
maxSize:
default: 100Gi
type: string
size:
default: 10Gi
type: string
type:
default: Filesystem
enum:
- Filesystem
- Block
type: string
type: object
type: object
sub_domain:
default: www
examples:
- www
type: string
dependencies:
- dist: null
category: dbo
component: ndb
- dist: null
category: dbo
component: redis
providers:
kubernetes: true
authentik: true
kubectl: true
postgresql: null
mysql: true
restapi: true
http: true
gitea: null
tfaddtype: null

View File

@@ -0,0 +1,67 @@
locals {
dns_name = "${var.sub_domain}.${var.domain_name}"
dns_names = [local.dns_name]
app_name = var.component == var.instance ? var.instance : format("%s-%s", var.component, var.instance)
icon = "logo192.png"
request_headers = {
"Content-Type" = "application/json"
Authorization = "Bearer ${data.kubernetes_secret_v1.authentik.data["AUTHENTIK_BOOTSTRAP_TOKEN"]}"
}
}
module "service" {
source = "git::https://git.solidite.fr/vynil/kydah-modules.git//service"
component = var.component
instance = var.instance
namespace = var.namespace
labels = local.common_labels
targets = ["http"]
providers = {
kubectl = kubectl
}
}
module "ingress" {
source = "git::https://git.solidite.fr/vynil/kydah-modules.git//ingress"
component = ""
instance = var.instance
namespace = var.namespace
issuer = var.issuer
ingress_class = var.ingress_class
labels = local.common_labels
dns_names = local.dns_names
middlewares = []
services = [module.service.default_definition]
providers = {
kubectl = kubectl
}
}
module "application" {
source = "git::https://git.solidite.fr/vynil/kydah-modules.git//application"
component = var.component
instance = var.instance
app_group = var.app_group
dns_name = local.dns_name
icon = local.icon
protocol_provider = module.oauth2.provider-id
providers = {
authentik = authentik
}
}
module "oauth2" {
source = "git::https://git.solidite.fr/vynil/kydah-modules.git//oauth2"
component = var.component
instance = var.instance
namespace = var.namespace
domain = var.domain
labels = local.common_labels
dns_name = local.dns_name
redirect_path = ""
providers = {
kubernetes = kubernetes
kubectl = kubectl
authentik = authentik
}
}

28
apps/wordpress/pvc.tf Normal file
View File

@@ -0,0 +1,28 @@
locals {
pvc_spec = merge({
"accessModes" = [var.storage.volume.accessMode]
"volumeMode" = var.storage.volume.type
"resources" = {
"requests" = {
"storage" = "${var.storage.volume.size}"
}
}
}, var.storage.volume.class != "" ?{
"storageClassName" = var.storage.volume.class
}:{})
}
resource "kubectl_manifest" "pvc" {
ignore_fields = ["spec.resources.requests.storage"]
yaml_body = <<-EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ${var.instance}
namespace: "${var.namespace}"
annotations:
k8up.io/backup: "true"
resize.kubesphere.io/storage_limit: "${var.storage.volume.maxSize}"
labels: ${jsonencode(local.common_labels)}
spec: ${jsonencode(local.pvc_spec)}
EOF
}

32
apps/wordpress/redis.tf Normal file
View File

@@ -0,0 +1,32 @@
locals {
redis-labels = merge(local.common_labels, {
"app.kubernetes.io/component" = "redis"
})
}
resource "kubectl_manifest" "dolibarr_redis" {
yaml_body = <<-EOF
apiVersion: "redis.redis.opstreelabs.in/v1beta1"
kind: "Redis"
metadata:
name: "${var.instance}-${var.component}-redis"
namespace: "${var.namespace}"
labels: ${jsonencode(local.redis-labels)}
spec:
kubernetesConfig:
image: "${var.images.redis.registry}/${var.images.redis.repository}:${var.images.redis.tag}"
imagePullPolicy: "${var.images.redis.pull_policy}"
storage:
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: "${var.storage.redis.size}"
redisExporter:
enabled: ${var.redis.exporter.enabled}
image: "${var.images.redis_exporter.registry}/${var.images.redis_exporter.repository}:${var.images.redis_exporter.tag}"
securityContext:
runAsUser: 1000
fsGroup: 1000
EOF
}

View File

@@ -0,0 +1,6 @@
const DEST=dest;
fn post_template() {
save_to_tf(`${global::DEST}/conditions.tf`, "conditions", #{
have_servicemonitors: have_crd("servicemonitors.monitoring.coreos.com")
});
}

View File

@@ -0,0 +1,236 @@
resource "kubectl_manifest" "wordpress_cfg" {
yaml_body = <<-EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: "${var.instance}-${var.component}-envs"
labels: ${jsonencode(local.common_labels)}
namespace: ${var.namespace}
data:
WORDPRESS_DB_HOST: ${var.instance}-${var.component}-mysqld.${var.namespace}.svc:3306
WORDPRESS_DB_NAME: ${mysql_database.component.name}
WORDPRESS_DB_USER: ${mysql_user.component.user}
WORDPRESS_HOST: ${local.dns_name}
WORDPRESS_TABLE_PREFIX: wp_
WORDPRESS_DEBUG: ""
WORDPRESS_CONFIG_EXTRA: |
#### general settings
define('WP_HOME', 'https://$${WORDPRESS_HOST}');
define('WP_SITEURL', 'https://$${WORDPRESS_HOST}');
define('WP_CACHE', true );
#### memory limits
# define('WP_MEMORY_LIMIT', '40' ); # default
# define('WP_MAX_MEMORY_LIMIT', '256' ); # default
EOF
}
resource "kubectl_manifest" "wordpress_files" {
yaml_body = <<-EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: "${var.instance}-${var.component}-files"
labels: ${jsonencode(local.common_labels)}
namespace: ${var.namespace}
data:
wp-cli: |-
#!/bin/sh
WP_PATH=/var/www/html/
CLI=/tmp/wp-cli.phar
if ! [ -f "$CLI" ]; then
curl https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar -o $CLI
fi
export PAGER="more"
php $CLI --path=$WP_PATH "$@"
docker-php-ext-redis.ini: |-
extension = redis.so
session.save_handler = redis
session.save_path = "tcp://${var.instance}-${var.component}-redis.${var.namespace}.svc:6379/?prefix=SESSION_${var.component}_${var.instance}:"
php-fpm-zz-docker.conf: |-
[global]
daemonize = no
[www]
listen = 8080
php-opcache-recommended.ini: |-
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.validate_timestamps=1
opcache.revalidate_freq=60
php-uploads.ini: |-
memory_limit = 256M
max_file_uploads = 50
upload_max_filesize = 96M
post_max_size = 96M
max_execution_time = 300
max_input_time = 600
nginx.conf: |-
worker_processes auto;
error_log /dev/stderr;
pid /tmp/nginx.pid;
worker_rlimit_nofile 8192;
events {
worker_connections 1024;
multi_accept on;
}
http {
# cache informations about FDs, frequently accessed files
# can boost performance, but you need to test those values
open_file_cache max=40000 inactive=20s;
open_file_cache_valid 60s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
# copies data between one FD and other from within the kernel
# faster than read() + write()
sendfile on;
# send headers in one piece, it is better than sending them one by one
tcp_nopush on;
# don't buffer data sent, good for small data bursts in real time
tcp_nodelay on;
# gzip settings
gzip on;
gzip_buffers 16 8k;
gzip_min_length 10k;
gzip_proxied any;
gzip_types
text/css
text/javascript
text/xml
text/plain
text/x-component
application/javascript
application/x-javascript
application/json
application/xml
application/rss+xml
application/atom+xml
font/truetype
font/opentype
application/vnd.ms-fontobject
image/svg+xml;
# allow the server to close connection on non responding client, this will free up memory
reset_timedout_connection on;
# request timed out -- default 60
client_body_timeout 20;
# if client stop responding, free up memory -- default 60
send_timeout 10;
# server will close connection after this time -- default 75
keepalive_timeout 30;
# number of requests client can make over keep-alive -- for testing environment
keepalive_requests 10000;
# other settings
client_max_body_size 96M;
server_tokens off;
include mime.types;
default_type application/octet-stream;
add_header X-Frame-Options SAMEORIGIN;
# trust these ips to set the correct http_x_forwarded_for header
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 127.0.0.1;
real_ip_header X-Forwarded-For;
# to boost I/O on HDD we can disable access logs
# access_log off;
log_format main '$remote_addr - $status [$request] $body_bytes_sent '
'"$http_referer" "$http_user_agent" via $realip_remote_addr';
access_log "/dev/stdout" main buffer=2048 flush=5s;
client_body_temp_path /tmp/client_temp 1 2;
proxy_temp_path /tmp/proxy_temp_path 1 2;
fastcgi_temp_path /tmp/fastcgi_temp 1 2;
uwsgi_temp_path /tmp/uwsgi_temp 1 2;
scgi_temp_path /tmp/scgi_temp 1 2;
####################################
### fastcgi cache start
#fastcgi_cache_path /tmp/fastcgi-cache levels=1:2 keys_zone=WORDPRESS:100m inactive=10m;
#fastcgi_cache_key "$scheme$request_method$host$request_uri";
#fastcgi_cache_use_stale error timeout invalid_header http_500;
#fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
### fastcgi cache end
####################################
server {
listen 8080 default_server;
server_name _;
root /var/www/html;
index index.php;
location / {
# deliver files directly or from php
# $uri - for regular files (html, css, js, jpg, ...)
# $uri/ - needed for indexes like /wp-config/ or /tag/nice/
# /index.php?$args - sends the request to wordpress using fastcgi / php
try_files $uri $uri/ /index.php?$args;
}
# DISABLE_DIRECT_CONTENT_PHP_EXECUTION
location ~ /(?:wp-content|wp-includes|uploads)/.*\.php$ {
deny all;
#access_log off;
#log_not_found off;
}
# Deny access to load load-scripts.php, load-styles.php; can be used for DOS attacks;
location ~ \/wp-admin\/load\-(scripts|styles)\.php {
deny all;
}
# START Nginx Rewrites for Rank Math Sitemaps
rewrite ^/sitemap_index.xml$ /index.php?sitemap=1 last;
rewrite ^/([^/]+?)-sitemap([0-9]+)?.xml$ /index.php?sitemap=$1&sitemap_n=$2 last;
# END Nginx Rewrites for Rank Math Sitemaps
####################################
### fastcgi cache start
# define when to skip the cache
#set $skip_cache 0;
# Requests with a query string should not be cached
#if ($query_string != "") {
# set $skip_cache 1;
#}
# Don't cache uris containing the following segments
#if ($request_uri ~ "/wp-admin/|/xmlrpc.php|wp-.*.php|index.php") {
# set $skip_cache 1;
#}
# Don't use the cache for logged in users or recent commenters
#if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
# set $skip_cache 1;
#}
### fastcgi cache end
####################################
# send .php requests to wordpress using (fastcgi)
location ~ [^/]\.php(/|$) {
# split the request path into its components
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
# check if the requested php file exits;
# don't send the request to fastcgi if no such file exits (saves some resources)
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
# include fastcgi_params from nginx directory (/etc/nginx/fastcgi_params)
include fastcgi_params;
# set the script filename (eg. /var/www/html/index.php)
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_index index.php;
# tell wordpress that the request came over https to avoid redirect-loops
fastcgi_param REQUEST_SCHEME 'https';
fastcgi_param HTTPS 'on';
# hide PHP header
fastcgi_hide_header X-Powered-By;
# send the request to php
fastcgi_pass localhost:9000;
#fastcgi_pass unix:/run/php/fpm.sock;
####################################
### fastcgi cache start
#fastcgi_cache_methods GET HEAD;
#fastcgi_cache_bypass $skip_cache;
#fastcgi_no_cache $skip_cache;
#fastcgi_cache WORDPRESS;
#fastcgi_cache_valid 10m;
#add_header X-FastCGI-Cache $upstream_cache_status;
### fastcgi cache end
####################################
}
# enable client cache for media files and fonts
location ~* \.(css|js|ico|gif|jpeg|jpg|webp|png|svg|eot|otf|woff|woff2|ttf|ogg|pdf)$ {
expires 120d;
}
}
}
EOF
}

View File

@@ -0,0 +1,147 @@
resource "random_password" "AUTH_KEY" {
length = 32
special = false
}
resource "random_password" "SECURE_AUTH_KEY" {
length = 32
special = false
}
resource "random_password" "LOGGED_IN_KEY" {
length = 32
special = false
}
resource "random_password" "NONCE_KEY" {
length = 32
special = false
}
resource "random_password" "AUTH_SALT" {
length = 32
special = false
}
resource "random_password" "SECURE_AUTH_SALT" {
length = 32
special = false
}
resource "random_password" "LOGGED_IN_SALT" {
length = 32
special = false
}
resource "random_password" "NONCE_SALT" {
length = 32
special = false
}
resource "kubectl_manifest" "secret" {
yaml_body = <<-EOF
apiVersion: v1
kind: Secret
metadata:
name: "${var.instance}-${var.component}"
labels: ${jsonencode(local.secret_labels)}
namespace: ${var.namespace}
stringData:
WORDPRESS_AUTH_KEY: "${random_password.AUTH_KEY.result}"
WORDPRESS_SECURE_AUTH_KEY: "${random_password.SECURE_AUTH_KEY.result}"
WORDPRESS_LOGGED_IN_KEY: "${random_password.LOGGED_IN_KEY.result}"
WORDPRESS_NONCE_KEY: "${random_password.NONCE_KEY.result}"
WORDPRESS_AUTH_SALT: "${random_password.AUTH_SALT.result}"
WORDPRESS_SECURE_AUTH_SALT: "${random_password.SECURE_AUTH_SALT.result}"
WORDPRESS_LOGGED_IN_SALT: "${random_password.LOGGED_IN_SALT.result}"
WORDPRESS_NONCE_SALT: "${random_password.NONCE_SALT.result}"
WORDPRESS_DB_PASSWORD: "${random_password.mysql_comp_pass.result}"
EOF
}
resource "kubectl_manifest" "pre_backup_sa" {
count = var.backups.enable?1:0
ignore_fields = ["metadata.annotations"]
yaml_body = <<-EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: "${var.instance}-${var.component}-backup-secret"
namespace: "${var.namespace}"
labels: ${jsonencode(local.secrets_labels)}
EOF
}
resource "kubectl_manifest" "pre_backup_role" {
count = var.backups.enable?1:0
ignore_fields = ["metadata.annotations"]
yaml_body = <<-EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: "${var.instance}-${var.component}-backup-secret"
namespace: "${var.namespace}"
labels: ${jsonencode(local.secrets_labels)}
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- list
EOF
}
resource "kubectl_manifest" "pre_backup_rb" {
count = var.backups.enable?1:0
ignore_fields = ["metadata.annotations"]
yaml_body = <<-EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: "${var.instance}-${var.component}-backup-secret"
namespace: "${var.namespace}"
labels: ${jsonencode(local.secrets_labels)}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: ${kubectl_manifest.pre_backup_role.name}
subjects:
- kind: ServiceAccount
name: ${kubectl_manifest.pre_backup_sa.name}
namespace: "${var.namespace}"
EOF
}
resource "kubectl_manifest" "pre_backup_pod_secret" {
count = var.backups.enable?1:0
ignore_fields = ["metadata.annotations"]
yaml_body = <<-EOF
apiVersion: k8up.io/v1
kind: PreBackupPod
metadata:
name: "${var.instance}-${var.component}-secret"
namespace: "${var.namespace}"
labels: ${jsonencode(local.secrets_labels)}
spec:
backupCommand: kubectl get secrets -o yaml -l k8up.io/backup=true
pod:
spec:
containers:
- command:
- cat
env:
- name: MYSQL_PWD
valueFrom:
secretKeyRef:
key: password
name: "${var.component}-${var.instance}"
image: "${var.images.kubectl.registry}/${var.images.kubectl.repository}:${var.images.kubectl.tag}"
imagePullPolicy: "${var.images.kubectl.pull_policy}"
name: secret
tty: true
serviceAccount: backup-secret
serviceAccountName: backup-secret
EOF
}

View File

@@ -0,0 +1,165 @@
resource "kubectl_manifest" "Deployment_wordpress" {
yaml_body = <<-EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: "${var.instance}-${var.component}"
labels: ${jsonencode(local.wp_all_labels)}
namespace: ${var.namespace}
spec:
replicas: 1
selector:
matchLabels: ${jsonencode(local.wp_labels)}
template:
metadata:
labels: ${jsonencode(local.wp_labels)}
spec:
serviceAccountName: default
securityContext:
fsGroup: 12000
runAsGroup: 12000
runAsNonRoot: true
runAsUser: 12000
initContainers:
- name: copy-wordpress-app
image: ${var.images.wordpress.registry}/${var.images.wordpress.repository}:${var.images.wordpress.tag}
imagePullPolicy: ${var.images.wordpress.pull_policy}
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
command: [sh, -cx]
args:
- >-
echo Copying Wordpress source ...;
ls -l /usr/src/wordpress/;
cp -r /usr/src/wordpress/. /wordpress-app/;
if [ -z "$(ls -A /wordpress-data/wp-content/)" ]; then echo "Copying initial files to wp-content ..."; cp -r /usr/src/wordpress/wp-content/* /wordpress-data/wp-content/; fi;
volumeMounts:
- mountPath: /wordpress-app/
name: wordpress-app
- mountPath: /wordpress-data/wp-content/
name: wordpress-data
subPath: wp-content
containers:
- name: wordpress
image: ${var.images.wordpress.registry}/${var.images.wordpress.repository}:${var.images.wordpress.tag}
imagePullPolicy: ${var.images.wordpress.pull_policy}
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
envFrom:
- configMapRef:
name: "${kubectl_manifest.wordpress_cfg.name}"
- secretRef:
name: "${kubectl_manifest.secret.name}"
resources: {}
ports:
- name: php-fpm
containerPort: 9000
protocol: TCP
livenessProbe:
initialDelaySeconds: 10
periodSeconds: 20
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 6
tcpSocket:
port: php-fpm
readinessProbe:
initialDelaySeconds: 10
periodSeconds: 20
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 6
tcpSocket:
port: php-fpm
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "test -f /var/www/html/wp-config.php && chmod 444 /var/www/html/wp-config.php"]
volumeMounts:
- mountPath: /var/www/html/
name: wordpress-app
- name: wordpress-data
mountPath: /var/www/html/wp-content/
subPath: wp-content
- name: wordpress-config
mountPath: /usr/local/etc/php-fpm.d/zz-docker.conf
subPath: php-fpm-zz-docker.conf
- name: wordpress-config
mountPath: /usr/local/etc/php/conf.d/uploads.ini
subPath: php-uploads.ini
- name: wordpress-config
mountPath: /usr/local/etc/php/conf.d/opcache-recommended.ini
subPath: php-opcache-recommended.ini
- name: wordpress-config
mountPath: /usr/local/etc/php/conf.d/docker-php-ext-redis.ini
subPath: docker-php-ext-redis.ini
- name: wordpress-config
mountPath: /usr/local/bin/wp
subPath: wp-cli
- name: nginx
image: ${var.images.nginx.registry}/${var.images.nginx.repository}:${var.images.nginx.tag}
imagePullPolicy: ${var.images.nginx.pull_policy}
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
ports:
- name: http
containerPort: 8080
livenessProbe:
initialDelaySeconds: 10
periodSeconds: 20
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 6
httpGet:
path: /wp-admin/install.php
port: http
scheme: HTTP
httpHeaders:
- name: X-Forwarded-Proto
value: https
readinessProbe:
initialDelaySeconds: 10
periodSeconds: 20
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 6
tcpSocket:
port: http
volumeMounts:
- mountPath: /var/www/html/
name: wordpress-app
- mountPath: /var/www/html/wp-content/
name: wordpress-data
subPath: wp-content
- mountPath: /etc/nginx/nginx.conf
name: wordpress-config
subPath: nginx.conf
- mountPath: /tmp/
name: nginx-tmp
volumes:
- name: wordpress-app
emptyDir: {}
- name: wordpress-config
configMap:
name: ${kubectl_manifest.wordpress_files.name}
- name: wordpress-data
persistentVolumeClaim:
claimName: ${kubectl_manifest.pvc.name}
- name: nginx-tmp
emptyDir:
medium: Memory
EOF
}