Add jumpers.stormcloudhills.com subdomain vhost (HTTP + HTTPS)
Build and Push Docker Image / build (push) Successful in 6s

Serve /uploads/scj as jumpers.stormcloudhills.com. HTTP redirects to
HTTPS; HTTPS vhost uses certs mounted at /etc/apache2/ssl. Adds named
ServerName to the default vhost so it remains the catch-all, scaffolds
the docroot, and documents expected cert filenames.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Jason Stedwell
2026-06-30 11:11:16 -05:00
parent 85c092b6ee
commit f189c3fe75
4 changed files with 114 additions and 1 deletions
+2 -1
View File
@@ -1,3 +1,4 @@
.env .env
docker/apache/ssl/ docker/apache/ssl/*
!docker/apache/ssl/README.md
docker/mysql/data/ docker/mysql/data/
+63
View File
@@ -1,4 +1,6 @@
<VirtualHost *:80> <VirtualHost *:80>
ServerName www.alwisp.net
ServerAlias alwisp.net
ServerAdmin webmaster@alwisp.net ServerAdmin webmaster@alwisp.net
DocumentRoot /var/www/html DocumentRoot /var/www/html
@@ -33,3 +35,64 @@
ErrorLog ${APACHE_LOG_DIR}/error.log ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost> </VirtualHost>
# Subdomain: jumpers.stormcloudhills.com -> /uploads/scj
# HTTP: redirect everything to HTTPS
<VirtualHost *:80>
ServerName jumpers.stormcloudhills.com
ServerAdmin webmaster@alwisp.net
RewriteEngine On
RewriteRule ^/?(.*)$ https://jumpers.stormcloudhills.com/$1 [R=301,L]
ErrorLog ${APACHE_LOG_DIR}/jumpers-error.log
CustomLog ${APACHE_LOG_DIR}/jumpers-access.log combined
</VirtualHost>
# HTTPS
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName jumpers.stormcloudhills.com
ServerAdmin webmaster@alwisp.net
DocumentRoot /var/www/html/uploads/scj
DirectoryIndex index.html
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/jumpers.stormcloudhills.com.crt
SSLCertificateKeyFile /etc/apache2/ssl/jumpers.stormcloudhills.com.key
# If your provider gives a separate CA chain/bundle, uncomment:
#SSLCertificateChainFile /etc/apache2/ssl/jumpers.stormcloudhills.com.chain.crt
<Directory /var/www/html/uploads/scj>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# Security headers
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# Compression
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/css text/javascript application/javascript application/json
</IfModule>
# Cache static assets
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/webp "access plus 1 month"
ExpiresByType image/svg+xml "access plus 1 month"
ExpiresByType text/css "access plus 1 week"
ExpiresByType application/javascript "access plus 1 week"
</IfModule>
ErrorLog ${APACHE_LOG_DIR}/jumpers-ssl-error.log
CustomLog ${APACHE_LOG_DIR}/jumpers-ssl-access.log combined
</VirtualHost>
</IfModule>
+37
View File
@@ -0,0 +1,37 @@
# Apache SSL certificates
This directory is mounted into the container at `/etc/apache2/ssl` (see `docker-compose.yml`).
Drop your TLS cert/key here. The actual `.crt`/`.key`/`.pem` files are gitignored — only this README is tracked.
## Files expected by the vhost config
For `jumpers.stormcloudhills.com` (`docker/apache/000-default.conf`):
| File | Purpose |
| --- | --- |
| `jumpers.stormcloudhills.com.crt` | Server certificate (SSLCertificateFile) |
| `jumpers.stormcloudhills.com.key` | Private key (SSLCertificateKeyFile) |
| `jumpers.stormcloudhills.com.chain.crt` | Optional CA chain/bundle (uncomment SSLCertificateChainFile to use) |
## Option A — Let's Encrypt (recommended for production)
Issue a cert on the host with certbot, then copy/symlink it in:
```sh
certbot certonly --standalone -d jumpers.stormcloudhills.com
cp /etc/letsencrypt/live/jumpers.stormcloudhills.com/fullchain.pem \
docker/apache/ssl/jumpers.stormcloudhills.com.crt
cp /etc/letsencrypt/live/jumpers.stormcloudhills.com/privkey.pem \
docker/apache/ssl/jumpers.stormcloudhills.com.key
```
Restart Apache after each renewal: `docker compose restart web`.
## Option B — Self-signed (local testing only; browsers will warn)
```sh
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout docker/apache/ssl/jumpers.stormcloudhills.com.key \
-out docker/apache/ssl/jumpers.stormcloudhills.com.crt \
-subj "/CN=jumpers.stormcloudhills.com"
```
+12
View File
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Storm Cloud Hills Jumpers</title>
</head>
<body>
<h1>jumpers.stormcloudhills.com</h1>
<p>Coming soon.</p>
</body>
</html>