Skip to content
Permalink
Browse files

Discontinue qemu-based deployment

It wasn't satisfying due to the negative impact on the host's startup
time, and the overall complexity of building the disk images.
  • Loading branch information...
lovett committed Nov 16, 2019
1 parent 3b7f1a0 commit 5b1bb63c2dd7dfc3932f07637cb0f29a242477b6
@@ -16,5 +16,6 @@
*.sqlite
*.bak
*.log
*.qcow2
*.img
/public/js/*.js
/public/css/*.css
*.tar.gz
106 Makefile
@@ -48,8 +48,9 @@ outdated: outdated-php outdated-js

# Install newly updated npm packages.
update-js: export NO_UPDATE_NOTIFIER=1
update-js: export DISABLE_OPENCOLLECTIVE=true
update-js:
npm update
npm install

# Install newly updated composer packages and update composer.lock
update-php:
@@ -97,11 +98,13 @@ install:


# Build the application in preparation for a production deployment
build:
npm run production
build: export DISABLE_OPENCOLLECTIVE=true
build: export COMPOSER_NO_INTERACTION=1
build: dummy
rm -f toils.tar.gz
rsync -a --cvs-exclude \
--delete \
--delete-excluded \
--exclude=.ac-php-conf.json \
--exclude=.ackrc \
--exclude=.env \
--exclude=.env.example \
@@ -111,99 +114,20 @@ build:
--exclude=node_modules \
--exclude=vendor \
--exclude=bootstrap/cache/* \
--exclude=build \
--exclude=storage \
--exclude=tests \
--exclude=package.json \
--exclude=package-lock.json \
--exclude=phpcs.xml \
--exclude=phpmd.xml \
--exclude=phpunit.xml \
--exclude=Makefile \
--exclude=mkimage.sh \
--exclude=server.php \
--exclude=*.sqlite \
--exclude=webpack.mix.js \
--exclude=*.qcow2 \
--exclude=.tar \
./ build
mkdir -p build/storage/framework/views
touch build/storage/$(SQLITE_DB_NAME)
cd build && composer install \
--no-dev \
--no-suggest \
--quiet \
--no-interaction \
--optimize-autoloader \
--classmap-authoritative
echo 'APP_KEY=' > build/.env
cd build && php artisan key:generate
cat $(HOME)/Documents/secrets/toils >> build/.env
cd build && php artisan config:cache
sed -i 's|$(PWD)/build|/mnt/toils-app|' build/bootstrap/cache/config.php
rm -rf build/storage
cd build && ln -sf /mnt/toils-storage storage
git checkout public/css/app.css public/js/app.js


# Build a QEMU virtual machine to run the application in production mode
image: toils-app.img toils-storage.qcow2 toils-os.qcow2

# Build a QEMU image for the OS.
toils-os.qcow2:
virt-builder debian-10 \
--format qcow2 \
-o toils-os.qcow2 \
--size 6G \
--hostname toils.local \
--root-password password:toils \
--append-line /etc/fstab:'LABEL=toils-app /mnt/toils-app ext4 defaults,noatime,noexec 0 0' \
--append-line /etc/fstab:'LABEL=toils-storage /mnt/toils-storage ext4 defaults,noatime,noexec 0 0' \
--run-command 'mkdir -p /etc/nginx/sites-enabled' \
--run-command 'mkdir -p /etc/php/7.3/fpm/pool.d' \
--run-command 'mkdir /mnt/toils-app' \
--run-command 'mkdir /mnt/toils-storage' \
--copy-in resources/qemu/toils-vhost.conf:/etc/nginx/sites-enabled \
--copy-in resources/qemu/toils-pool.conf:/etc/php/7.3/fpm/pool.d \
--copy-in resources/qemu/toils-setup.sh:/usr/local/sbin \
--copy-in resources/qemu/toils-setup.service:/etc/systemd/system \
--uninstall man-db \
--run-command 'apt autoremove -y' \
--firstboot resources/qemu/toils-firstboot.sh

# Build a QEMU image separate from the OS image for the application files.
# Without the extra 10M, the image runs out of space.
toils-app.img: build
virt-make-fs --format=raw --size=+10M --type=ext4 --label=toils-app build toils-app.img

# Build a QEMU image separate from the OS image to store volatile data.
toils-storage.qcow2:
qemu-img create -f qcow2 toils-storage.qcow2 50G
guestfish add toils-storage.qcow2 : \
run : \
mkfs ext4 /dev/sda : \
set-label /dev/sda toils-storage : \
mount /dev/sda / : \
mkdir-p /app/public : \
mkdir-p /framework/views : \
mkdir /fonts : \
mkdir /logs : \
touch /$(SQLITE_DB_NAME)

# Run the QEMU virtual machine locally
testrun:
qemu-system-x86_64 -m 256M \
-accel kvm \
-nic user,hostfwd=tcp::$(LOCAL_PORT)-:80 \
-nographic \
-drive file=toils-os.qcow2,index=0,media=disk,format=qcow2 \
-drive file=toils-app.img,index=1,media=disk,format=raw \
-drive file=toils-storage.qcow2,index=2,media=disk,format=qcow2

shrink:
qemu-img convert -O qcow2 toils-storage.qcow2 toils-storage-shrunk.qcow2
mv toils-storage-shrunk.qcow2 toils-storage.qcow2

clean:
rm -f toils-os.qcow2
rm -f toils-app.img
rm -f toils-storage.qcow2
rm -rf build
cd build && mkdir -p storage/framework/views
cd build && touch storage/$(SQLITE_DB_NAME)
cd build && npm ci && npm run production
cd build && composer install --no-dev --no-suggest --quiet --classmap-authoritative
cd build && rm composer.lock composer.json package.json package-lock.json webpack.mix.js
tar --create --gzip --file=toils.tar.gz --exclude=node_modules --exclude=storage --transform s/build/toils/ build
@@ -2,59 +2,134 @@
- hosts: toils
vars:
application_name: toils
image_dir: /srv/qemu
application_root: /srv
application_user: www-data
application_group: www-data
application_hostname: "{{ application_name }}.{{ host_domain }}"
nginx_vhost_path: "/etc/nginx/sites-available/{{ application_name }}"

tasks:
- name: Create directory to store VM images
become: yes
- name: Build application
local_action:
module: make
chdir: "{{ playbook_dir }}/../"
target: build

- name: Install system packages
become: true
apt:
name:
- php-bcmath
- php-fpm
- php-json
- php-mbstring
- php-sqlite3
- php-tokenizer
- php-xml
- sqlite3
state: latest
force_apt_get: yes

- name: Install PHP-FPM pool
become: true
template:
src: "templates/toils-pool.j2"
dest: "/etc/php/7.3/fpm/pool.d/toils.conf"
notify: Restart PHP-FPM

- name: Install Nginx Vhost
become: true
template:
src: "templates/toils-vhost.j2"
dest: "{{ nginx_vhost_path }}"
notify: Restart Nginx

- name: Enable Nginx Vhost
become: true
file:
src: "{{ nginx_vhost_path }}"
dest: "/etc/nginx/sites-enabled/{{ application_name }}"
state: link

- name: Create non-local application storage
become: true
file:
path: "{{ image_dir }}"
path: "{{ item }}"
state: directory
mode: "0700"
owner: "{{ application_user }}"
group: "{{ application_group }}"
loop:
- "/var/{{ application_name}}/app"
- "/var/{{ application_name}}/fonts"
- "/var/{{ application_name}}/framework/views"
- "/var/{{ application_name}}/logs"

- name: OS and Storage images
- name: Create application database
become: true
file:
path: "/var/{{ application_name }}/{{application_name }}.sqlite"
state: touch
owner: "{{ application_user }}"
group: "{{ application_group }}"

- name: Delete previous installation
become: yes
copy:
src: "{{ item }}"
dest: "{{ image_dir }}/"
mode: "0700"
force: no
setype: virt_image_t
with_items:
- "../toils-os.qcow2"
- "../toils-storage.qcow2"

- name: App image
file:
path: "{{ application_root }}/{{ application_name }}"
state: absent

- name: Transfer and extract application
become: yes
copy:
src: "../toils-app.img"
dest: "{{ image_dir }}"
mode: "0700"
backup: yes
setype: virt_image_t

- name: Systemd service
unarchive:
src: "../{{ application_name }}.tar.gz"
dest: "{{ application_root }}"
owner: "{{ application_user }}"
group: "{{ application_group }}"

- name: Symlink non-local storage
become: true
file:
src: "/var/{{ application_name }}"
dest: "{{ application_root }}/{{ application_name }}/storage"
state: link
owner: "{{ application_user }}"
group: "{{ application_group }}"

- name: Run database migrations
command: "php artisan migrate --force"
become: yes
template:
src: "templates/systemd-service.j2"
dest: "/etc/systemd/system/toils.service"
args:
chdir: "{{ application_root }}/{{ application_name }}"

- name: Start systemd service
- name: Optimize application
command: "{{ item }}"
become: yes
args:
chdir: "{{ application_root }}/{{ application_name }}"
loop:
- "php artisan config:clear"
- "php artisan config:cache"
- "php artisan route:clear"
- "php artisan route:cache"
- "php artisan view:clear"
- "php artisan view:cache"
environment:
APP_KEY: "{{ toils_app_key }}"
MAIL_HOST: "{{ toils_mail_host }}"
MAIL_USERNAME: "{{ toils_mail_username }}"
MAIL_PASSWORD: "{{ toils_mail_password }}"
MAIL_FROM_NAME: "{{ application_name }}"
MAIL_FROM_ADDRESS: "{{ toils_mail_from_address }}"
APP_URL: "{{ toils_app_url }}"

handlers:
- name: Restart PHP-FPM
become: true
systemd:
name: php7.3-fpm.service
state: restarted
- name: Restart Nginx
become: true
systemd:
daemon_reload: yes
enabled: yes
masked: no
name: "{{ application_name }}"
state: started

# - name: Build production container image
# local_action:
# module: make
# chdir: "{{ playbook_dir }}/../"
# target: image

# - name: Stop service
# systemd:
# scope: user
# name: "{{ application_name }}"
# state: stopped
name: nginx.service
state: restarted

This file was deleted.

@@ -11,3 +11,7 @@ pm.min_spare_servers = 1
pm.max_spare_servers = 3
php_admin_value[upload_max_filesize] = 50M
php_admin_value[post_max_size] = 60M

; Local Variables:
; mode: conf
; End:
@@ -0,0 +1,31 @@
# -*- mode: nginx -*-

server {
listen 80;
listen [::]:80;
server_name {{ application_hostname }};
return 301 https://$host$request_uri;
}

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name {{ application_hostname }};
ssl_certificate {{ letsencrypt_certificate }};
ssl_certificate_key {{ letsencrypt_key }};

root {{ application_root }}/{{ application_name }}/public;

index index.html index.php;

client_max_body_size 60M;

location / {
try_files $uri $uri/ /index.php?$query_string;
}

location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/{{ application_name }}.sock;
}
}

0 comments on commit 5b1bb63

Please sign in to comment.
You can’t perform that action at this time.