Add Apache2 and lighttpd static build deployment options
This commit is contained in:
Vendored
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"timestamp": "2026-04-18T20:33:42.828Z"
|
"timestamp": "2026-04-18T20:40:09.901Z"
|
||||||
}
|
}
|
||||||
Vendored
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"timestamp": "2026-04-18T20:33:44.083Z"
|
"timestamp": "2026-04-18T20:40:11.126Z"
|
||||||
}
|
}
|
||||||
@@ -2,5 +2,5 @@
|
|||||||
"files": {},
|
"files": {},
|
||||||
"turnCycles": 0,
|
"turnCycles": 0,
|
||||||
"maxCycles": 3,
|
"maxCycles": 3,
|
||||||
"lastUpdated": "2026-04-18T20:33:44.083Z"
|
"lastUpdated": "2026-04-18T20:40:11.126Z"
|
||||||
}
|
}
|
||||||
+393
-301
@@ -1,311 +1,403 @@
|
|||||||
# Deployment Guide
|
# Deployment Guide
|
||||||
|
|
||||||
Complete setup for deploying the portfolio site with Docker, Caddy, and Oracle Cloud VPS.
|
Complete setup for deploying the portfolio site with various web servers.
|
||||||
|
|
||||||
## Architecture
|
## Architecture Options
|
||||||
|
|
||||||
|
### Option A: Static Build (Recommended for Production)
|
||||||
```
|
```
|
||||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
Cloudflare → VPS (Apache/lighttpd/Caddy) → dist/ (static files)
|
||||||
│ Cloudflare │────▶│ Oracle VPS │────▶│ Vite Dev │
|
```
|
||||||
│ (DNS + Proxy) │ │ (Caddy) │ │ Server │
|
|
||||||
│ │ │ Port 80/443 │────▶│ Port 5173 │
|
### Option B: Vite Dev Server (Development)
|
||||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
```
|
||||||
│
|
Cloudflare → VPS (Caddy) → Vite Dev Server (port 5173)
|
||||||
▼
|
```
|
||||||
┌─────────────────┐
|
|
||||||
│ Docker │
|
## Quick Start: Static Build
|
||||||
│ (Caddy) │
|
|
||||||
└─────────────────┘
|
The simplest and most efficient approach:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/peters-portfolio-site
|
||||||
|
git pull
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
# Now serve the dist/ folder with any web server
|
||||||
|
```
|
||||||
|
|
||||||
|
## Option 1: Apache2
|
||||||
|
|
||||||
|
### Install Apache
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install apache2
|
||||||
|
sudo systemctl enable apache2
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build and Deploy
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/peters-portfolio-site
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# Copy docs to dist for serving
|
||||||
|
cp -r public/docs dist/
|
||||||
|
|
||||||
|
# Deploy to Apache
|
||||||
|
sudo rm -rf /var/www/pwlmyers.org/*
|
||||||
|
sudo cp -r dist/* /var/www/pwlmyers.org/
|
||||||
|
sudo chown -R www-data:www-data /var/www/pwlmyers.org
|
||||||
|
```
|
||||||
|
|
||||||
|
### Apache Configuration
|
||||||
|
|
||||||
|
Create `/etc/apache2/sites-available/pwlmyers.org.conf`:
|
||||||
|
|
||||||
|
```apache
|
||||||
|
<VirtualHost *:80>
|
||||||
|
ServerName pwlmyers.org
|
||||||
|
ServerAlias www.pwlmyers.org
|
||||||
|
DocumentRoot /var/www/pwlmyers.org
|
||||||
|
|
||||||
|
# Enable rewrite for SPA routing
|
||||||
|
<Directory /var/www/pwlmyers.org>
|
||||||
|
Options -Indexes +FollowSymLinks
|
||||||
|
AllowOverride All
|
||||||
|
Require all granted
|
||||||
|
|
||||||
|
# Handle client-side routing
|
||||||
|
RewriteEngine On
|
||||||
|
RewriteBase /
|
||||||
|
RewriteRule ^index\.html$ - [L]
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-d
|
||||||
|
RewriteRule . /index.html [L]
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
# Enable compression
|
||||||
|
<IfModule mod_deflate.c>
|
||||||
|
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css
|
||||||
|
AddOutputFilterByType DEFLATE application/javascript application/json
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
# Cache static assets
|
||||||
|
<IfModule mod_expires.c>
|
||||||
|
ExpiresActive On
|
||||||
|
ExpiresByType image/png "access plus 1 month"
|
||||||
|
ExpiresByType image/jpeg "access plus 1 month"
|
||||||
|
ExpiresByType text/css "access plus 1 week"
|
||||||
|
ExpiresByType application/javascript "access plus 1 week"
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
ErrorLog ${APACHE_LOG_DIR}/pwlmyers-error.log
|
||||||
|
CustomLog ${APACHE_LOG_DIR}/pwlmyers-access.log combined
|
||||||
|
</VirtualHost>
|
||||||
|
```
|
||||||
|
|
||||||
|
Enable the site:
|
||||||
|
```bash
|
||||||
|
sudo a2ensite pwlmyers.org.conf
|
||||||
|
sudo a2enmod rewrite deflate expires headers
|
||||||
|
sudo systemctl restart apache2
|
||||||
|
```
|
||||||
|
|
||||||
|
### SSL with Certbot
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install certbot python3-certbot-apache
|
||||||
|
sudo certbot --apache -d pwlmyers.org
|
||||||
|
```
|
||||||
|
|
||||||
|
## Option 2: lighttpd
|
||||||
|
|
||||||
|
### Install lighttpd
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install lighttpd
|
||||||
|
sudo systemctl enable lighttpd
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build and Deploy
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/peters-portfolio-site
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
cp -r public/docs dist/
|
||||||
|
|
||||||
|
sudo mkdir -p /var/www/pwlmyers.org
|
||||||
|
sudo rm -rf /var/www/pwlmyers.org/*
|
||||||
|
sudo cp -r dist/* /var/www/pwlmyers.org/
|
||||||
|
sudo chown -R www-data:www-data /var/www/pwlmyers.org
|
||||||
|
```
|
||||||
|
|
||||||
|
### lighttpd Configuration
|
||||||
|
|
||||||
|
Edit `/etc/lighttpd/lighttpd.conf` or create `/etc/lighttpd/conf-available/99-pwlmyers.conf`:
|
||||||
|
|
||||||
|
```lighttpd
|
||||||
|
server.document-root = "/var/www/pwlmyers.org"
|
||||||
|
server.port = 80
|
||||||
|
server.bind = "0.0.0.0"
|
||||||
|
server.tag = "lighttpd"
|
||||||
|
|
||||||
|
# Server name
|
||||||
|
server.name = "pwlmyers.org"
|
||||||
|
|
||||||
|
# Index file
|
||||||
|
index-file.names = ( "index.html" )
|
||||||
|
|
||||||
|
# MIME types
|
||||||
|
mimetype.assign = (
|
||||||
|
".html" => "text/html",
|
||||||
|
".htm" => "text/html",
|
||||||
|
".css" => "text/css",
|
||||||
|
".js" => "application/javascript",
|
||||||
|
".json" => "application/json",
|
||||||
|
".png" => "image/png",
|
||||||
|
".jpg" => "image/jpeg",
|
||||||
|
".jpeg" => "image/jpeg",
|
||||||
|
".gif" => "image/gif",
|
||||||
|
".svg" => "image/svg+xml",
|
||||||
|
".ico" => "image/x-icon",
|
||||||
|
".pdf" => "application/pdf",
|
||||||
|
".pptx" => "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
||||||
|
".docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Enable mod_rewrite for SPA routing
|
||||||
|
server.modules += ( "mod_rewrite" )
|
||||||
|
url.rewrite-if-not-file = (
|
||||||
|
"^/(.*)$" => "/index.html"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Enable compression
|
||||||
|
server.modules += ( "mod_deflate" )
|
||||||
|
deflate.mimetypes = ( "text/html", "text/plain", "text/css", "application/javascript" )
|
||||||
|
deflate.allowed-encodings = ( "gzip", "deflate" )
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
server.modules += ( "mod_setenv" )
|
||||||
|
setenv.add-response-header += (
|
||||||
|
"X-Frame-Options" => "SAMEORIGIN",
|
||||||
|
"X-Content-Type-Options" => "nosniff",
|
||||||
|
"X-XSS-Protection" => "1; mode=block",
|
||||||
|
"Referrer-Policy" => "strict-origin-when-cross-origin"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
server.errorlog = "/var/log/lighttpd/error.log"
|
||||||
|
accesslog.filename = "/var/log/lighttpd/access.log"
|
||||||
|
|
||||||
|
# File upload limits (for large PPTX/PDF files)
|
||||||
|
server.max-request-size = 104857600 # 100MB
|
||||||
|
```
|
||||||
|
|
||||||
|
Enable and restart:
|
||||||
|
```bash
|
||||||
|
sudo lighty-enable-mod pwlmyers
|
||||||
|
sudo systemctl restart lighttpd
|
||||||
|
```
|
||||||
|
|
||||||
|
### SSL with Certbot
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install certbot
|
||||||
|
sudo certbot certonly --standalone -d pwlmyers.org
|
||||||
|
```
|
||||||
|
|
||||||
|
Then configure lighttpd for SSL (see certbot output for paths).
|
||||||
|
|
||||||
|
## Option 3: Caddy (Static Files)
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/peters-portfolio-site
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
cp -r public/docs dist/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Caddyfile
|
||||||
|
|
||||||
|
```caddy
|
||||||
|
pwlmyers.org {
|
||||||
|
root * /opt/peters-portfolio-site/dist
|
||||||
|
file_server
|
||||||
|
try_files {path} {path}/ /index.html
|
||||||
|
|
||||||
|
# Handle docs directory
|
||||||
|
handle /docs/* {
|
||||||
|
uri strip_prefix /docs
|
||||||
|
root * /opt/peters-portfolio-site/dist/docs
|
||||||
|
file_server
|
||||||
|
}
|
||||||
|
|
||||||
|
log {
|
||||||
|
output file /var/log/caddy/access.log
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Option 4: Nginx
|
||||||
|
|
||||||
|
### Install Nginx
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install nginx
|
||||||
|
sudo systemctl enable nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/peters-portfolio-site
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
cp -r public/docs dist/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Nginx Configuration
|
||||||
|
|
||||||
|
Create `/etc/nginx/sites-available/pwlmyers.org`:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name pwlmyers.org www.pwlmyers.org;
|
||||||
|
root /var/www/pwlmyers.org;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# Gzip compression
|
||||||
|
gzip on;
|
||||||
|
gzip_types text/plain text/css application/json application/javascript text/xml;
|
||||||
|
|
||||||
|
# Cache static assets
|
||||||
|
location ~* \.(jpg|jpeg|png|gif|ico|css|js|pdf)$ {
|
||||||
|
expires 1M;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Serve docs correctly
|
||||||
|
location /docs/ {
|
||||||
|
alias /var/www/pwlmyers.org/docs/;
|
||||||
|
autoindex off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# SPA routing - serve index.html for all non-file routes
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
|
||||||
|
# File upload size (for docs)
|
||||||
|
client_max_body_size 100M;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Enable:
|
||||||
|
```bash
|
||||||
|
sudo ln -s /etc/nginx/sites-available/pwlmyers.org /etc/nginx/sites-enabled/
|
||||||
|
sudo rm /etc/nginx/sites-enabled/default # Remove default
|
||||||
|
sudo nginx -t
|
||||||
|
sudo systemctl restart nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
## Updating Static Build
|
||||||
|
|
||||||
|
Create a deploy script `/opt/peters-portfolio-site/deploy.sh`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cd /opt/peters-portfolio-site
|
||||||
|
|
||||||
|
echo "Pulling latest changes..."
|
||||||
|
git pull
|
||||||
|
|
||||||
|
echo "Installing dependencies..."
|
||||||
|
npm install
|
||||||
|
|
||||||
|
echo "Building..."
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
echo "Copying docs..."
|
||||||
|
cp -r public/docs dist/
|
||||||
|
|
||||||
|
echo "Deploying to web server..."
|
||||||
|
# For Apache:
|
||||||
|
sudo rm -rf /var/www/pwlmyers.org/*
|
||||||
|
sudo cp -r dist/* /var/www/pwlmyers.org/
|
||||||
|
sudo chown -R www-data:www-data /var/www/pwlmyers.org
|
||||||
|
|
||||||
|
# For lighttpd:
|
||||||
|
# sudo rm -rf /var/www/pwlmyers.org/*
|
||||||
|
# sudo cp -r dist/* /var/www/pwlmyers.org/
|
||||||
|
# sudo chown -R www-data:www-data /var/www/pwlmyers.org
|
||||||
|
# sudo systemctl restart lighttpd
|
||||||
|
|
||||||
|
echo "Done!"
|
||||||
|
```
|
||||||
|
|
||||||
|
Make executable:
|
||||||
|
```bash
|
||||||
|
chmod +x /opt/peters-portfolio-site/deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Comparison
|
||||||
|
|
||||||
|
| Server | RAM Usage | Ease of Config | SSL | Best For |
|
||||||
|
|--------|-----------|----------------|-----|----------|
|
||||||
|
| Apache | High | Medium | Certbot | Complex setups |
|
||||||
|
| Nginx | Low | Medium | Certbot | High traffic |
|
||||||
|
| lighttpd | Very Low | Easy | Manual | Resource constrained |
|
||||||
|
| Caddy | Low | Very Easy | Auto | Simplicity |
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### 404 on refresh (SPA routing)
|
||||||
|
|
||||||
|
Ensure rewrite rules are configured to serve `index.html` for non-file paths.
|
||||||
|
|
||||||
|
### Docs not downloading
|
||||||
|
|
||||||
|
Check MIME types are configured for `.pptx`, `.docx`, `.pdf`.
|
||||||
|
|
||||||
|
### Permission denied
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo chown -R www-data:www-data /var/www/pwlmyers.org
|
||||||
|
sudo chmod -R 755 /var/www/pwlmyers.org
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Apache
|
||||||
|
sudo tail -f /var/log/apache2/pwlmyers-error.log
|
||||||
|
|
||||||
|
# lighttpd
|
||||||
|
sudo tail -f /var/log/lighttpd/error.log
|
||||||
|
|
||||||
|
# Nginx
|
||||||
|
sudo tail -f /var/log/nginx/error.log
|
||||||
```
|
```
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- Oracle Cloud VPS (or similar)
|
All options require:
|
||||||
- Domain name (Cloudflare recommended)
|
- Domain pointing to VPS (A record)
|
||||||
- Docker + Docker Compose installed
|
- Ports 80/443 open in Oracle Cloud security list
|
||||||
- Git access to repository
|
- Node.js 20.19+ for building
|
||||||
|
|
||||||
## Server Setup
|
See [README.md](README.md) for development setup.
|
||||||
|
|
||||||
### 1. Provision VPS
|
|
||||||
|
|
||||||
**Oracle Cloud Free Tier:**
|
|
||||||
1. Create instance (Ubuntu 22.04/24.04 ARM or AMD)
|
|
||||||
2. Add ingress rules for ports 22, 80, 443
|
|
||||||
3. Note the public IP
|
|
||||||
|
|
||||||
**Open Ports in Oracle Console:**
|
|
||||||
1. Networking → Virtual Cloud Networks
|
|
||||||
2. Click your VCN → Subnets
|
|
||||||
3. Security Lists → Default Security List
|
|
||||||
4. Add Ingress Rules:
|
|
||||||
- TCP 80 from 0.0.0.0/0
|
|
||||||
- TCP 443 from 0.0.0.0/0
|
|
||||||
- TCP 22 from your IP (SSH)
|
|
||||||
|
|
||||||
### 2. Install Dependencies
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Update system
|
|
||||||
sudo apt update && sudo apt upgrade -y
|
|
||||||
|
|
||||||
# Install Docker
|
|
||||||
curl -fsSL https://get.docker.com | sh
|
|
||||||
sudo usermod -aG docker $USER
|
|
||||||
newgrp docker
|
|
||||||
|
|
||||||
# Install Node.js 22
|
|
||||||
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
|
|
||||||
sudo apt install -y nodejs
|
|
||||||
|
|
||||||
# Verify
|
|
||||||
node -v # Should be 20.19+ or 22.12+
|
|
||||||
npm -v
|
|
||||||
docker --version
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Clone Repository
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo mkdir -p /opt/peters-portfolio-site
|
|
||||||
sudo chown $USER:$USER /opt/peters-portfolio-site
|
|
||||||
cd /opt/peters-portfolio-site
|
|
||||||
git clone https://git.dustin.coffee/hobokenchicken/peters-portfolio-site.git .
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Configure Caddy
|
|
||||||
|
|
||||||
Create directory structure:
|
|
||||||
```bash
|
|
||||||
mkdir -p docker_configs/caddy/conf
|
|
||||||
mkdir -p docker_configs/caddy/site
|
|
||||||
mkdir -p docker_configs/caddy/caddy_data
|
|
||||||
mkdir -p docker_configs/caddy/caddy_config
|
|
||||||
mkdir -p docker_configs/caddy/logs
|
|
||||||
```
|
|
||||||
|
|
||||||
Create `docker_configs/caddy/conf/Caddyfile`:
|
|
||||||
|
|
||||||
```caddy
|
|
||||||
pwlmyers.org {
|
|
||||||
reverse_proxy 172.20.1.232:5173
|
|
||||||
|
|
||||||
log {
|
|
||||||
output file /var/log/caddy/access.log
|
|
||||||
format json
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optional: Add headers
|
|
||||||
header {
|
|
||||||
X-Content-Type-Options nosniff
|
|
||||||
X-Frame-Options DENY
|
|
||||||
X-XSS-Protection "1; mode=block"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note:** Adjust `172.20.1.232` to match your Vite server's IP (check with `ip addr show`)
|
|
||||||
|
|
||||||
### 5. Docker Compose for Caddy
|
|
||||||
|
|
||||||
Create `compose.caddy.yaml`:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
services:
|
|
||||||
caddy:
|
|
||||||
image: caddy:latest
|
|
||||||
restart: unless-stopped
|
|
||||||
ports:
|
|
||||||
- "80:80"
|
|
||||||
- "443:443"
|
|
||||||
- "443:443/udp"
|
|
||||||
volumes:
|
|
||||||
- ./docker_configs/caddy/conf:/etc/caddy
|
|
||||||
- ./docker_configs/caddy/site:/srv
|
|
||||||
- ./docker_configs/caddy/caddy_data:/data
|
|
||||||
- ./docker_configs/caddy/caddy_config:/config
|
|
||||||
- ./docker_configs/caddy/logs:/var/log/caddy
|
|
||||||
networks:
|
|
||||||
- caddy_network
|
|
||||||
|
|
||||||
networks:
|
|
||||||
caddy_network:
|
|
||||||
driver: bridge
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6. DNS Configuration (Cloudflare)
|
|
||||||
|
|
||||||
1. Log into Cloudflare dashboard
|
|
||||||
2. Select your domain
|
|
||||||
3. **DNS** tab → Add records:
|
|
||||||
- Type: `A`
|
|
||||||
- Name: `@` (root) or `www`
|
|
||||||
- Content: `150.136.209.11` (your VPS IP)
|
|
||||||
- Proxy status: 🟠 Orange cloud (proxied) or ⚪ Gray cloud (DNS only)
|
|
||||||
- TTL: Auto
|
|
||||||
|
|
||||||
4. **SSL/TLS** tab:
|
|
||||||
- Mode: **Full (strict)** or **Full**
|
|
||||||
- Always Use HTTPS: On
|
|
||||||
|
|
||||||
### 7. Deploy Application
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /opt/peters-portfolio-site
|
|
||||||
|
|
||||||
# Copy docs to public
|
|
||||||
cp -r docs/* public/docs/
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
npm install
|
|
||||||
|
|
||||||
# Start Vite dev server (background)
|
|
||||||
nohup npm run dev > vite.log 2>&1 &
|
|
||||||
|
|
||||||
# Start Caddy
|
|
||||||
docker compose -f compose.caddy.yaml up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8. Verify Deployment
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Check Caddy is running
|
|
||||||
docker ps | grep caddy
|
|
||||||
|
|
||||||
# Check Vite is running
|
|
||||||
ps aux | grep vite
|
|
||||||
curl http://172.20.1.232:5173/
|
|
||||||
|
|
||||||
# Test from VPS
|
|
||||||
curl -H "Host: pwlmyers.org" http://localhost/
|
|
||||||
|
|
||||||
# Test HTTPS (after DNS propagates)
|
|
||||||
curl -v https://pwlmyers.org/
|
|
||||||
```
|
|
||||||
|
|
||||||
## Updates
|
|
||||||
|
|
||||||
### Pull and Update
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /opt/peters-portfolio-site
|
|
||||||
|
|
||||||
# Pull latest changes
|
|
||||||
git pull
|
|
||||||
|
|
||||||
# Reinstall if package.json changed
|
|
||||||
npm install
|
|
||||||
|
|
||||||
# Copy any new docs
|
|
||||||
cp -r docs/* public/docs/
|
|
||||||
|
|
||||||
# Restart Vite
|
|
||||||
pkill -f vite || true
|
|
||||||
nohup npm run dev > vite.log 2>&1 &
|
|
||||||
|
|
||||||
# Restart Caddy if config changed
|
|
||||||
docker compose -f compose.caddy.yaml restart
|
|
||||||
```
|
|
||||||
|
|
||||||
### View Logs
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Vite logs
|
|
||||||
tail -f vite.log
|
|
||||||
|
|
||||||
# Caddy logs
|
|
||||||
docker logs -f ubuntu-caddy-1
|
|
||||||
tail -f docker_configs/caddy/logs/access.log
|
|
||||||
```
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### SSL Certificate Issues
|
|
||||||
|
|
||||||
If Caddy fails to get Let's Encrypt certificate:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Check Cloudflare proxy status
|
|
||||||
dig pwlmyers.org +short
|
|
||||||
# Should return your VPS IP, not Cloudflare IPs
|
|
||||||
|
|
||||||
# If using Cloudflare proxy (orange cloud):
|
|
||||||
# - Use Cloudflare Origin Certificate
|
|
||||||
# - Or switch to DNS only (gray cloud) for Let's Encrypt
|
|
||||||
```
|
|
||||||
|
|
||||||
### Port Already in Use
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Find what's using port 80/443
|
|
||||||
sudo netstat -tlnp | grep -E ':(80|443)'
|
|
||||||
|
|
||||||
# Stop conflicting service
|
|
||||||
sudo systemctl stop nginx apache2
|
|
||||||
```
|
|
||||||
|
|
||||||
### Vite Not Accessible
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Check Vite is listening on all interfaces
|
|
||||||
netstat -tlnp | grep 5173
|
|
||||||
|
|
||||||
# Should show 0.0.0.0:5173, not 127.0.0.1:5173
|
|
||||||
|
|
||||||
# Check allowedHosts in vite.config.ts
|
|
||||||
cat vite.config.ts
|
|
||||||
```
|
|
||||||
|
|
||||||
### Docker Network Issues
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Check Caddy can reach Vite
|
|
||||||
docker exec ubuntu-caddy-1 wget -qO- http://172.20.1.232:5173/
|
|
||||||
|
|
||||||
# If using Docker network instead of host IP:
|
|
||||||
docker network ls
|
|
||||||
docker network inspect caddy_caddy_network
|
|
||||||
```
|
|
||||||
|
|
||||||
## Alternative: Systemd Service
|
|
||||||
|
|
||||||
Instead of `nohup`, create a systemd service for Vite:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo tee /etc/systemd/system/peters-portfolio.service > /dev/null <<'EOF'
|
|
||||||
[Unit]
|
|
||||||
Description=Peter's Portfolio Vite Dev Server
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User=ubuntu
|
|
||||||
WorkingDirectory=/opt/peters-portfolio-site
|
|
||||||
ExecStart=/usr/bin/npm run dev
|
|
||||||
Restart=always
|
|
||||||
RestartSec=10
|
|
||||||
Environment=NODE_ENV=development
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
sudo systemctl enable peters-portfolio
|
|
||||||
sudo systemctl start peters-portfolio
|
|
||||||
sudo systemctl status peters-portfolio
|
|
||||||
```
|
|
||||||
|
|
||||||
## Security Notes
|
|
||||||
|
|
||||||
- Keep `node_modules` updated: `npm audit fix`
|
|
||||||
- Use Cloudflare proxy for DDoS protection
|
|
||||||
- Consider fail2ban for SSH brute force protection
|
|
||||||
- Regular backups of `docs/` directory
|
|
||||||
|
|
||||||
## Support
|
|
||||||
|
|
||||||
For issues with:
|
|
||||||
- **Application code:** Check README.md troubleshooting section
|
|
||||||
- **Server/Docker:** Check logs with commands above
|
|
||||||
- **DNS/SSL:** Verify Cloudflare settings and Oracle firewall rules
|
|
||||||
|
|||||||
@@ -45,6 +45,16 @@ npm run dev
|
|||||||
|
|
||||||
The dev server runs at `http://localhost:5173/` by default.
|
The dev server runs at `http://localhost:5173/` by default.
|
||||||
|
|
||||||
|
### Production Build (Recommended)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
# Serve dist/ folder with Apache, Nginx, lighttpd, or Caddy
|
||||||
|
```
|
||||||
|
|
||||||
|
See [DEPLOYMENT.md](DEPLOYMENT.md) for server configuration examples.
|
||||||
|
|
||||||
### Build for Production
|
### Build for Production
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
Reference in New Issue
Block a user