Skillversitas

Apache on a MicroVM

Run the Apache HTTP Server in a MicroVM to serve web applications. Apache is heavier than Nginx but more flexible thanks to its modular design.

Preparing the Image

sudo mount -o loop rootfs.img /mnt/microvm

# Debian/Ubuntu
sudo chroot /mnt/microvm bash -c '
  apt update && apt install -y apache2
  a2enmod rewrite
  a2enmod proxy
  a2enmod proxy_http
'

# Alpine
sudo chroot /mnt/microvm bash -c '
  apk add apache2 apache2-proxy
'

sudo umount /mnt/microvm

Optimal Configuration

sudo mount -o loop rootfs.img /mnt/microvm

sudo tee /mnt/microvm/etc/apache2/conf-available/microvm.conf << 'APACHECONF'
# Performance tuning for MicroVM
ServerRoot "/etc/apache2"
PidFile ${APACHE_PID_FILE}
Timeout 30
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5

# MPM Event (most efficient)
<IfModule mpm_event_module>
    StartServers            2
    MinSpareThreads         25
    MaxSpareThreads         75
    ThreadLimit             64
    ThreadsPerChild         25
    MaxRequestWorkers       100
    MaxConnectionsPerChild  1000
</IfModule>

# Logging
ErrorLog /var/log/apache2/error.log
LogLevel warn
APACHECONF

sudo chroot /mnt/microvm a2enconf microvm
sudo umount /mnt/microvm

Running the MicroVM

qemu-system-x86_64 \
  -M microvm -enable-kvm -cpu host -m 512m -smp 2 \
  -kernel vmlinuz \
  -append "console=ttyS0 root=/dev/vda rw" \
  -drive id=rootfs,file=rootfs.img,format=raw,if=none,cache=none \
  -device virtio-blk-device,drive=rootfs \
  -netdev user,id=net0,hostfwd=tcp::8080-:80 \
  -device virtio-net-device,netdev=net0 \
  -nographic -serial stdio

Setting Up the Virtual Host

# Create the document root
mkdir -p /var/www/html

# Create an index page
cat > /var/www/html/index.html << 'HTML'
<!DOCTYPE html>
<html>
<head><title>Apache on MicroVM</title></head>
<body>
  <h1>Apache HTTP Server on QEMU MicroVM</h1>
  <p>Server is running successfully!</p>
</body>
</html>
HTML

# Virtual host config
cat > /etc/apache2/sites-available/000-default.conf << 'VHOST'
<VirtualHost *:80>
    ServerName localhost
    DocumentRoot /var/www/html

    <Directory /var/www/html>
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
VHOST

Reverse Proxy Setup

# Enable modules
a2enmod proxy
a2enmod proxy_http

# Create the proxy config
cat > /etc/apache2/sites-available/proxy.conf << 'PROXY'
<VirtualHost *:80>
    ServerName proxy.local

    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:3000/
    ProxyPassReverse / http://127.0.0.1:3000/
</VirtualHost>
PROXY

a2ensite proxy
systemctl restart apache2

Auto Start

sudo tee /mnt/microvm/etc/init.d/apache2 << 'APACHEINIT'
#!/sbin/openrc-run

APACHE2=/usr/sbin/apache2
PIDFILE=/run/apache2.pid

depend() {
    need net
    keyword timeout 60
}

start() {
    ebegin "Starting Apache2"
    mkdir -p /run/apache2
    $APACHE2 -f /etc/apache2/apache2.conf -DFOREGROUND &
    echo $! > $PIDFILE
    eend $?
}

stop() {
    ebegin "Stopping Apache2"
    kill $(cat $PIDFILE) 2>/dev/null
    eend $?
}
APACHEINIT

sudo chmod +x /mnt/microvm/etc/init.d/apache2
sudo chroot /mnt/microvm rc-update add apache2 default

SSL/TLS (Let's Encrypt)

# Install certbot
apt install -y certbot python3-certbot-apache

# Obtain certificate
certbot --apache -d example.com -d www.example.com

# Auto renew
echo "0 12 * * * /usr/bin/certbot renew --quiet" | crontab -

Performance Tuning

# Enable compression
a2enmod deflate

# Check the modules
apachectl -M

# Test config
apachectl configtest

# Benchmark
ab -n 1000 -c 10 http://localhost/

Troubleshooting

Port 80 is already in use

# Check what is using port 80
ss -tlnp | grep :80

# Stop the other service or change the port
Listen 8080

Out of memory

# Reduce MaxRequestWorkers
MaxRequestWorkers 50

# Use mpm_event instead of mpm_prefork
a2dismod mpm_prefork
a2enmod mpm_event

# Disable unused modules
a2dismod autoindex
a2dismod negotiation

Permission error

# Set permissions
chown -R www-data:www-data /var/www/html
chmod -R 755 /var/www/html