diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 0000000..da45a6f --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,23 @@ +VAGRANTFILE_API_VERSION = "2" + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + config.vm.box = "ubuntu/jammy64" + + config.vm.network "private_network", ip: "10.0.0.18", + virtualbox__intnet: true + + config.vm.provider "virtualbox" do |vb| + vb.memory = 4096 + end + + config.vm.synced_folder "salt/srv/", "/srv/" + + config.vm.provision :salt do |salt| + salt.minion_config = "salt/etc/salt/minion" + salt.run_highstate = true + salt.bootstrap_options = "-P -c /tmp" + salt.verbose = true + salt.log_level = "info" + salt.colorize = true + end +end diff --git a/salt/etc/salt/minion b/salt/etc/salt/minion new file mode 100644 index 0000000..4e76d60 --- /dev/null +++ b/salt/etc/salt/minion @@ -0,0 +1,18 @@ +# This is masterless setup. +file_client: local + +environment: prod + +file_roots: # Salt states root directories. + base: + - /srv/salt/base # Base configuration (fallback). + prod: + - /srv/salt/prod # Production configuration. + - /srv/salt/base # And fallback to base. + +pillar_roots: # Pillar data directories. Contains sensitive data. + base: + - /srv/pillar/base # Base data directory. + prod: + - /srv/pillar/prod # Production data directory. + - /srv/pillar/base # And fallback to base. diff --git a/salt/srv/salt/base/elasticsearch/init.sls b/salt/srv/salt/base/elasticsearch/init.sls new file mode 100644 index 0000000..abebda7 --- /dev/null +++ b/salt/srv/salt/base/elasticsearch/init.sls @@ -0,0 +1,26 @@ +{% for vhost,config in pillar["vhosts"].items() %} +Prepare elasticsearch volume for {{ vhost }}: + docker_volume.present: + - name: elasticsearch-{{ vhost }} + - driver: local + +Run Elasticsearch container for {{ vhost }}: + docker_container.running: + - name: elasticsearch-{{ vhost }} + - image: docker.elastic.co/elasticsearch/elasticsearch:7.17.10 + - start: True + - restart: always + - networks: + - network-{{ vhost }} + - environment: + - xpack.security.enabled=false + - discovery.type=single-node + - ES_JAVA_OPTS=-Xms{{ config.elastic_heap_min }} -Xmx{{ config.elastic_heap_max }} + - binds: + - elasticsearch-{{ vhost }}:/usr/share/elasticsearch/data + - healthcheck: + - test: [ "CMD", "curl", "--fail" , "http://elasticsearch-{{ vhost }}:9200/_cluster/health?wait_for_status=green&timeout=5s", "||", "exit", "1" ] + - interval: {{ 5e9 | int }} # 5s + - timeout: {{ 5e9 | int }} # 5s + - retries: 5 +{% endfor %} \ No newline at end of file diff --git a/salt/srv/salt/base/magento/init.sls b/salt/srv/salt/base/magento/init.sls new file mode 100644 index 0000000..2ddc85a --- /dev/null +++ b/salt/srv/salt/base/magento/init.sls @@ -0,0 +1,35 @@ +{% for vhost, config in pillar["vhosts"].items() %} +Deploy magento for {{ vhost }}: + module.run: + - name: docker.run + - m_name: php-fpm-{{ vhost }} + - cmd: | + COMPOSER_HOME=/var/www/html \ + COMPOSER_AUTH="{\"http-basic\": {\"repo.magento.com\": {\"username\": \"{{ config.magento_marketplace_public }}\",\"password\":\"{{ config.magento_marketplace_private }}\" }}}" \ + sudo -E -u www-data composer create-project --working-dir=/app --repository-url=https://repo.magento.com/ magento/project-community-edition=2.4.6 /app + +Setup magento for {{ vhost }}: + module.run: + - name: docker.run + - m_name: php-fpm-{{ vhost }} + - cmd: | + sudo -E -u www-data php -dmemory_limit={{ config.php_maxmem_deploy }} -f bin/magento setup:install --base-url=http://{{ vhost }}:{{ config.nginx_port }} --db-host=mysql-{{ vhost }} --db-name={{ config.mysql_database }} --db-user={{ config.mysql_user }} --db-password={{ config.mysql_password }} --admin-firstname={{ config.magento_admin_firstname }} --admin-lastname={{ config.magento_admin_lastname }} --admin-email={{ config.magento_admin_email }} --admin-user={{ config.magento_admin_user }} --admin-password={{ config.magento_admin_pass }} --language=en_US --currency=USD --timezone=Europe/Bratislava --use-rewrites=1 --elasticsearch-host=elasticsearch-{{ vhost }} --search-engine=elasticsearch7 + +{% if config.magento_sample_products %} +Deploy sampledata for {{ vhost }}: + module.run: + - name: docker.run + - m_name: php-fpm-{{ vhost }} + - cmd: | + COMPOSER_HOME=/var/www/html \ + COMPOSER_AUTH="{\"http-basic\": {\"repo.magento.com\": {\"username\": \"{{ config.magento_marketplace_public }}\",\"password\":\"{{ config.magento_marketplace_private }}\" }}}" \ + sudo -E -u www-data php -dmemory_limit={{ config.php_maxmem_deploy }} -f bin/magento sampledata:deploy +{% endif %} + +Run Magento upgrade for {{ vhost }}: + module.run: + - name: docker.run + - m_name: php-fpm-{{ vhost }} + - cmd: | + sudo -E -u www-data php -dmemory_limit={{ config.php_maxmem_deploy }} -f bin/magento setup:upgrade +{% endfor %} \ No newline at end of file diff --git a/salt/srv/salt/base/mariadb/init.sls b/salt/srv/salt/base/mariadb/init.sls new file mode 100644 index 0000000..0efdaeb --- /dev/null +++ b/salt/srv/salt/base/mariadb/init.sls @@ -0,0 +1,23 @@ +{% for vhost, config in pillar["vhosts"].items() %} +Prepare mariadb volume for {{ vhost }}: + docker_volume.present: + - name: mysql-{{ vhost }} + - driver: local + +Run MariaDB container for {{ vhost }}: + docker_container.running: + - name: mysql-{{ vhost }} + - image: mariadb:10.4 + - start: True + - restart: always + + - networks: + - network-{{ vhost }} + - environment: + - MARIADB_RANDOM_ROOT_PASSWORD=yes + - MARIADB_DATABASE={{ config.mysql_database }} + - MARIADB_USER={{ config.mysql_user }} + - MARIADB_PASSWORD={{ config.mysql_password }} + - binds: + - mysql-{{ vhost }}:/var/lib/mysql +{% endfor %} \ No newline at end of file diff --git a/salt/srv/salt/base/memcached-docker/init.sls b/salt/srv/salt/base/memcached-docker/init.sls new file mode 100644 index 0000000..94f482e --- /dev/null +++ b/salt/srv/salt/base/memcached-docker/init.sls @@ -0,0 +1,10 @@ +{% for vhost,config in pillar["vhosts"].items() %} +Run memcached container for {{ vhost }}: + docker_container.running: + - name: memcached-{{ vhost }} + - image: memcached + - start: True + - restart: always + - networks: + - network-{{ vhost }} +{% endfor %} \ No newline at end of file diff --git a/salt/srv/salt/base/nginx-docker/files/default.conf b/salt/srv/salt/base/nginx-docker/files/default.conf new file mode 100644 index 0000000..6dbace8 --- /dev/null +++ b/salt/srv/salt/base/nginx-docker/files/default.conf @@ -0,0 +1,188 @@ +upstream fastcgi_backend { + server php-fpm-{{ vhost }}:9000; +} + +server { + listen 80; + server_name 127.0.0.1 localhost; + + set $MAGE_ROOT /app; + set $MAGE_MODE developer; + + root $MAGE_ROOT/pub; + + index index.php; + autoindex off; + charset off; + + add_header 'X-Content-Type-Options' 'nosniff'; + + location /setup { + root $MAGE_ROOT; + + location ~ ^/setup/index.php { + fastcgi_pass fastcgi_backend; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_read_timeout 600; + fastcgi_send_timeout 600; + fastcgi_buffer_size 128k; + fastcgi_buffers 4 256k; + include fastcgi_params; + } + + location ~ ^/setup/(?!pub/). { + deny all; + } + + location ~ ^/setup/pub/ { + add_header X-Frame-Options "SAMEORIGIN"; + } + } + + location /update { + root $MAGE_ROOT; + + location ~ ^/update/index.php { + fastcgi_split_path_info ^(/update/index.php)(/.+)$; + fastcgi_pass fastcgi_backend; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_read_timeout 600; + fastcgi_send_timeout 600; + fastcgi_buffer_size 128k; + fastcgi_buffers 4 256k; + include fastcgi_params; + } + + # deny everything but index.php + location ~ ^/update/(?!pub/). { + deny all; + } + + location ~ ^/update/pub/ { + add_header X-Frame-Options "SAMEORIGIN"; + } + } + + location / { + try_files $uri $uri/ /index.php?$args; + } + + location /pub { + location ~ ^/pub/media/(downloadable|customer|import|theme_customization/.*\.xml) { + deny all; + } + + alias $MAGE_ROOT/pub; + add_header X-Frame-Options "SAMEORIGIN"; + } + + location /static/ { + if ($MAGE_MODE = "production") { + expires max; + } + + # remove signature of static files used to overcome browser cache + location ~ ^/static/version { + rewrite ^/static/(version\d*/)?(.*)$ /static/$2 last; + } + + location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ { + add_header Cache-Control "public"; + add_header X-Frame-Options "SAMEORIGIN"; + expires +1y; + + if (!-f $request_filename) { + rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last; + } + } + + location ~* \.(zip|gz|gzip|bz2|csv|xml)$ { + add_header Cache-Control "no-store"; + add_header X-Frame-Options "SAMEORIGIN"; + expires off; + + if (!-f $request_filename) { + rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last; + } + } + + if (!-f $request_filename) { + rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last; + } + + add_header X-Frame-Options "SAMEORIGIN"; + } + + location /media/ { + try_files $uri $uri/ /get.php?$args; + + location ~ ^/media/theme_customization/.*\.xml { + deny all; + } + + location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ { + add_header Cache-Control "public"; + add_header X-Frame-Options "SAMEORIGIN"; + expires +1y; + try_files $uri $uri/ /get.php?$args; + } + + location ~* \.(zip|gz|gzip|bz2|csv|xml)$ { + add_header Cache-Control "no-store"; + add_header X-Frame-Options "SAMEORIGIN"; + expires off; + try_files $uri $uri/ /get.php?$args; + } + + add_header X-Frame-Options "SAMEORIGIN"; + } + + location /media/customer/ { + deny all; + } + + location /media/downloadable/ { + deny all; + } + + location /media/import/ { + deny all; + } + + location ~ /media/theme_customization/.*\.xml$ { + deny all; + } + + location /errors/ { + try_files $uri =404; + } + + location ~ ^/errors/.*\.(xml|phtml)$ { + deny all; + } + + location ~ cron\.php { + deny all; + } + + location ~ (index|get|static|report|404|503)\.php$ { + try_files $uri =404; + fastcgi_pass fastcgi_backend; + + fastcgi_param PHP_FLAG "session.auto_start=off \n suhosin.session.cryptua=off"; + + fastcgi_read_timeout 600s; + fastcgi_connect_timeout 600s; + fastcgi_param MAGE_MODE $MAGE_MODE; + + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + + fastcgi_buffer_size 128k; + fastcgi_buffers 4 256k; + } +} \ No newline at end of file diff --git a/salt/srv/salt/base/nginx-docker/init.sls b/salt/srv/salt/base/nginx-docker/init.sls new file mode 100644 index 0000000..9633750 --- /dev/null +++ b/salt/srv/salt/base/nginx-docker/init.sls @@ -0,0 +1,23 @@ +{% for vhost, config in pillar["vhosts"].items() %} +Copy nginx configuration for {{ vhost }}: + file.managed: + - name: /usr/local/vhost-conf/{{ vhost }}/nginx.conf + - source: salt://nginx-docker/files/default.conf + - makedirs: True + - template: jinja + - vhost: {{ vhost }} + +Run nginx container for {{ vhost }}: + docker_container.running: + - name: nginx-{{ vhost }} + - image: nginx:1.25 + - start: True + - restart: always + - networks: + - network-{{ vhost }} + - binds: + - webroot-{{ vhost }}:/app:rw,Z + - /usr/local/vhost-conf/{{ vhost }}/nginx.conf:/etc/nginx/conf.d/default.conf:ro + - port_bindings: + - {{ config.nginx_port }}:80 +{% endfor %} \ No newline at end of file diff --git a/salt/srv/salt/base/php-fpm-docker/files/Dockerfile b/salt/srv/salt/base/php-fpm-docker/files/Dockerfile new file mode 100644 index 0000000..132669b --- /dev/null +++ b/salt/srv/salt/base/php-fpm-docker/files/Dockerfile @@ -0,0 +1,154 @@ +FROM php:8.1-fpm + +ARG APP_ROOT=/app + +ENV PHP_VALIDATE_TIMESTAMPS 1 +ENV DEBUG false +ENV PHP_EXTENSIONS bcmath bz2 calendar exif gd gettext intl mysqli opcache pdo_mysql redis soap sockets sodium sysvmsg sysvsem sysvshm xsl zip pcntl + +# Install dependencies +RUN apt-get update \ + && apt-get upgrade -y \ + && apt-get install -y --no-install-recommends \ + apt-utils \ + sendmail-bin \ + sendmail \ + sudo \ + iproute2 \ + git \ + gnupg2 \ + ca-certificates \ + lsb-release \ + software-properties-common \ + libbz2-dev \ + libjpeg62-turbo-dev \ + libpng-dev \ + libfreetype6-dev \ + libgmp-dev \ + libgpgme11-dev \ + libicu-dev \ + libldap2-dev \ + libpcre3-dev \ + libpspell-dev \ + libtidy-dev \ + libxslt1-dev \ + libyaml-dev \ + libzip-dev \ + zip \ + unzip \ + acl \ + cron \ + curl \ + wget \ + libaudit1 \ + libbrotli1 \ + libbsd0 \ + libbz2-1.0 \ + libcap-ng0 \ + libcom-err2 \ + libcrypt1 \ + libcurl4 \ + libexpat1 \ + libffi7 \ + libfftw3-double3 \ + libfontconfig1 \ + libfreetype6 \ + libgcc-s1 \ + libgcrypt20 \ + libglib2.0-0 \ + libgmp10 \ + libgnutls30 \ + libgomp1 \ + libgpg-error0 \ + libgssapi-krb5-2 \ + libhogweed6 \ + libicu67 \ + libidn2-0 \ + libjpeg62-turbo \ + libk5crypto3 \ + libkeyutils1 \ + libkrb5-3 \ + libkrb5support0 \ + liblcms2-2 \ + libldap-2.4-2 \ + liblqr-1-0 \ + libltdl7 \ + liblzma5 \ + libmagickcore-6.q16-6 \ + libmagickwand-6.q16-6 \ + libmd0 \ + libmemcached11 \ + libncurses6 \ + libnettle8 \ + libnghttp2-14 \ + libonig5 \ + libp11-kit0 \ + libpam0g \ + libpcre2-8-0 \ + libpcre3 \ + libz-dev \ + libmemcached-dev \ + libmemcached-tools \ + && rm -rf /var/lib/apt/lists/* + +# Configure the gd library +RUN docker-php-ext-configure \ + gd --with-freetype=/usr/include/ --with-jpeg=/usr/include/ +RUN docker-php-ext-configure \ + opcache --enable-opcache + +# Install required PHP extensions +RUN docker-php-ext-install -j$(nproc) \ + bcmath \ + bz2 \ + calendar \ + exif \ + gd \ + gettext \ + gmp \ + intl \ + mysqli \ + opcache \ + pdo_mysql \ + pspell \ + shmop \ + soap \ + sockets \ + sysvmsg \ + sysvsem \ + sysvshm \ + tidy \ + xsl \ + zip \ + pcntl + +RUN pecl install -o -f \ + gnupg \ + mailparse \ + msgpack \ + oauth \ + pcov \ + raphf \ + redis \ + xdebug-3.1.5 \ + xmlrpc-1.0.0RC3 \ + yaml \ + memcached + +RUN docker-php-ext-enable memcached + + + +# Install Composer +RUN wget -O composer-setup.php https://getcomposer.org/installer +RUN php composer-setup.php --install-dir=/usr/local/bin --filename=composer +RUN chmod +x /usr/local/bin/composer + +RUN mkdir -p ${APP_ROOT} + +# Delete default config file +RUN rm /usr/local/etc/php-fpm.d/zz-docker.conf + +RUN chown -R www-data:www-data /usr/local /var/www /var/log /usr/local/etc/php/conf.d ${APP_ROOT} + +WORKDIR ${APP_ROOT} \ No newline at end of file diff --git a/salt/srv/salt/base/php-fpm-docker/files/www.conf b/salt/srv/salt/base/php-fpm-docker/files/www.conf new file mode 100644 index 0000000..e8f0286 --- /dev/null +++ b/salt/srv/salt/base/php-fpm-docker/files/www.conf @@ -0,0 +1,36 @@ +[global] +daemonize = no + +[www] +user = www-data +group = www-data + +listen = 9000 +listen.backlog = -1 + +pm = dynamic +pm.max_children = {{ php_max_children }} +pm.start_servers = 5 +pm.min_spare_servers = 5 +pm.max_spare_servers = 10 +pm.process_idle_timeout = 10s; +pm.max_requests = 100 + +request_slowlog_timeout = 0 +request_terminate_timeout = 0 +rlimit_files = 1024 +rlimit_core = 0 + +chdir = / + +catch_workers_output = yes +security.limit_extensions = .php .php3 .php4 .php5 + +php_admin_value[session.save_handler] = memcached +php_admin_value[session.save_path] = "memcached-{{ vhost }}:11211" + +env[HOSTNAME] = $HOSTNAME +env[PATH] = /usr/local/bin:/usr/bin:/bin +env[TMP] = /tmp +env[TMPDIR] = /tmp +env[TEMP] = /tmp \ No newline at end of file diff --git a/salt/srv/salt/base/php-fpm-docker/init.sls b/salt/srv/salt/base/php-fpm-docker/init.sls new file mode 100644 index 0000000..fe9bf46 --- /dev/null +++ b/salt/srv/salt/base/php-fpm-docker/init.sls @@ -0,0 +1,53 @@ +Copy Dockerfile: + file.managed: + - name: /storage/php-fpm-docker/Dockerfile + - source: salt://php-fpm-docker/files/Dockerfile + - makedirs: True + +Build php-fpm-docker: + docker_image.present: + - name: php-fpm-docker + - build: /storage/php-fpm-docker + - tag: latest + +Remove Dockerfile from /srv: + file.absent: + - name: /storage/php-fpm-docker + +{% for vhost, config in pillar["vhosts"].items() %} +Copy php-fpm configuration for {{ vhost }}: + file.managed: + - name: /usr/local/etc/vhost-conf/{{ vhost }}/php.conf + - source: salt://php-fpm-docker/files/www.conf + - template: jinja + - vhost: {{ vhost }} + - php_max_children: {{ config.php_max_children }} + - makedirs: True + +Prepare webroot volume for {{ vhost }}: + docker_volume.present: + - name: webroot-{{ vhost }} + - driver: local + +Run php-fpm container for {{ vhost }}: + docker_container.running: + - name: php-fpm-{{ vhost }} + - image: php-fpm-docker + - start: True + - restart: always + - networks: + - network-{{ vhost }} + - binds: + - webroot-{{ vhost }}:/app:rw,Z + - /usr/local/etc/vhost-conf/{{ vhost }}/php.conf:/usr/local/etc/php-fpm.d/www.conf:ro + +Fix permissions on the directory for {{ vhost }}: + file.directory: + - name: /var/lib/docker/volumes/webroot-{{ vhost }}/_data + - user: 33 + - group: 33 + - mode: 755 # will not recurse mode as stated below + - recurse: + - user + - group +{% endfor %} \ No newline at end of file